文章目录
- 获取源码
- 1、后台管理——菜品起售停售
- 前端请求数据分析
- 编写方法
- 2、后台管理——菜品删除
- 前端请求数据分析
- 编写方法
- 3、后台管理——修改套餐
- 前端请求分析
- 方法一:完成点击修改时数据的回显
- 方法二:修改套餐
- 4、后台管理——启停售套餐
- 前端请求分析
- 编写方法
- 5、后台管理——订单明细分页查询
- 前端请求分析
- 编写方法
- 运行结果
- 6、后台管理——订单操作
- 前端请求分析
- 编写方法
- 7、客户端——退出登录
- 前端请求分析
- 编写方法
- 8、客户端——购物车商品减少
- 前端请求分析
- 编写方法
- 9、客户端——查看订单
- 前端请求分析
- 准备工作
- 编写方法
- 运行结果
- 10、客户端——订单完成后再来一单
- 前端请求分析
- 编写方法
本项目是基于自学b站中 黑马程序员 的瑞吉外卖项目:视频链接: 黑马程序员Java项目实战《瑞吉外卖》,轻松掌握springboot + mybatis plus开发核心技术的真java实战项目_哔哩哔哩_bilibili
自己把视频中一些没实现的功能给实现了;本人技术可能不到位,笔记仅供参考学习使用;
本人自己把视频中老师没讲的功能都给实现了
获取源码
1、后台管理——菜品起售停售
前端请求数据分析
-
单个停售起售
-
批量起售停售
通过请求分析,我们可以看到单个启停售与批量启停售都是请求的同一个地址。传的status是个RestFul风格,ids是个集合。
编写方法
-
@PostMapping(“/status/{status}”):请求地址
-
@PathVariable:绑定占位符
-
@RequestParam:前端参数名与后端要一致,用于接收前端传过来的集合
/** * 菜品启用停售 * * @param status * @param ids * @return */ @PostMapping("/status/{status}") public R<String> status( @PathVariable int status,@RequestParam List<Long> ids ) { log.info("status:{}=========ids:{}", status, ids); List<Dish> dishList = dishService.listByIds(ids); for (Dish dish : dishList) { dish.setStatus(status); } dishService.updateBatchById(dishList); return R.success("菜品状态修改成功"); }
2、后台管理——菜品删除
前端请求数据分析
- 删除单个菜品
- 批量删除菜品
这里可以看到无论是删除单个菜品还是批量删除菜品都是请求的同一个地址,所以这里也是只需要编写一个方法即可
编写方法
/**
* 删除菜品
* @param ids
* @return
*/
@DeleteMapping
public R<String> delete(@RequestParam List<Long> ids ) {
log.info("要删除的菜品id:{}",ids);
dishService.removeByIds(ids);
return R.success("删除菜品成功");
}
3、后台管理——修改套餐
前端请求分析
-
当单击修改套餐时,我们发现有一个请求404所以我们只需要完成这一个请求的方法编写即可
-
当我们保存修改时也有一个请求404,需要完成
方法一:完成点击修改时数据的回显
-
Servicer层
/** * 根据ID查询套餐,同时查询关联额菜品数据 * @param id * @return */ public SetmealDto setmealDishById(Long id);
-
impl层
/** * 根据ID查询套餐,同时查询关联额菜品数据 * @param id * @return */ @Override public SetmealDto setmealDishById(Long id){ //获取套餐ID Setmeal setmeal = this.getById(id); //对象拷贝 SetmealDto setmealDto = new SetmealDto(); BeanUtils.copyProperties(setmeal,setmealDto); //构造条件构造器 LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>(); //查询套餐关联的菜品 queryWrapper.eq(SetmealDish::getSetmealId,id); List<SetmealDish> list = setmealDishService.list(queryWrapper); //设置套餐关联的菜品 setmealDto.setSetmealDishes(list); return setmealDto; }
-
controller层
/** * 根据ID查询套餐以及关联的菜品 * @param id * @return */ @GetMapping("/{id}") public R<SetmealDto> get(@PathVariable Long id ){ log.info("根据ID查询套餐信息ID:{}",id); SetmealDto setmealDto = setmealService.setmealDishById(id); return R.success(setmealDto); }
方法二:修改套餐
-
service层
/** * 更新套餐信息同时更新关联的菜品数据 * @param setmealDto */ public void updateSetmealDish(SetmealDto setmealDto);
-
impl层:这里操作了两张表加上事物
/** * 更新套餐信息同时更新关联的菜品数据 * @param setmealDto */ @Transactional @Override public void updateSetmealDish( SetmealDto setmealDto ) { //更新套餐数据 this.updateById(setmealDto); //获取套餐ID Long setmealId = setmealDto.getId(); //构造条件构造器 LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>(); //删除套餐关联的菜品 queryWrapper.eq(SetmealDish::getSetmealId, setmealId); setmealDishService.remove(queryWrapper); //添加新的套餐关联菜品 List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes(); //菜品关联套餐ID setmealDishes = setmealDishes.stream().map(( item ) -> { item.setSetmealId(setmealId); return item; }).collect(Collectors.toList()); //保存套餐和菜品的关联信息,操作setmeal_dish,执行insert操作 setmealDishService.saveBatch(setmealDishes); }
-
controller层
/** * 更新套餐信息同时更新关联的菜品数据 * @param setmealDto * @return */ @PutMapping public R<String > update(@RequestBody SetmealDto setmealDto){ log.info("修改套餐数据:",setmealDto); setmealService.updateSetmealDish(setmealDto); return R.success("修改成功"); }
4、后台管理——启停售套餐
前端请求分析
- 停售起售单个套餐
- 批量起停售套餐
看到单个启停售与批量启停售使用的都是一个请求,所以我们这里创建一个方法即可完成
编写方法
- 此方法与菜单启停售方法半斤八两
/** * 套餐启停售 * @param status * @param ids * @return */ @PostMapping("/status/{status}") public R<String> status(@PathVariable int status,@RequestParam List<Long> ids){ log.info("修改套餐状态:status:{}-----------ids:{}",status,ids); List<Setmeal> setmeals = setmealService.listByIds(ids); //跟新状态 setmeals=setmeals.stream().map((item)->{ item.setStatus(status); return item; }).collect(Collectors.toList()); setmealService.updateBatchById(setmeals); return R.success("套餐状态修改成功"); }
5、后台管理——订单明细分页查询
前端请求分析
- 当我们单击订单明细子功能时发送了一个请求,同时还发现通过参数请求时也发送的是同一个请求,所以我们只需要在后端编写一个方法来处理就可以了
- 点击订单明细子功能
- 添加时间参数
- 添加关键字
- 添加关键字同时添加时间参数
- 点击订单明细子功能
编写方法
-
@DateTimeFormat
:接收前端数据- pattern:用于指定时间格式
/** * 分页查询订单信息 * @param page * @param pageSize * @param number * @param beginTime * @param endTime * @return */ @GetMapping("/page") public R<Page<Orders>> page( int page, int pageSize, Long number, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime beginTime,@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime){ log.info("订单明细查询"); //分页构造器 Page<Orders> ordersPage = new Page<>(page,pageSize); //条件构造器 LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>(); //添加查询条件number模糊查询 queryWrapper.like(number!=null,Orders::getNumber,number); //添加查询条件起始时间 queryWrapper.ge(beginTime!=null,Orders::getOrderTime,beginTime); //添加查询条件结束时间 queryWrapper.le(endTime!=null,Orders::getOrderTime,endTime); //添加排序条件 queryWrapper.orderByDesc(Orders::getOrderTime); ordersService.page(ordersPage,queryWrapper); return R.success(ordersPage); }
运行结果
6、后台管理——订单操作
前端请求分析
- 通过请求分析,可以得到数据是以JSON传送的,后端我们可以使用
Orders
对象接收
编写方法
/**
* 订单状态跟新
* @param orders
* @return
*/
@PutMapping
public R<String> update(@RequestBody Orders orders){
log.info("订单操作orders:+{}",orders);
//更新状态
ordersService.updateById(orders);
return R.success("状态更新成功");
}
7、客户端——退出登录
前端请求分析
- 前端并没有传参,所以后端只需要把Session移除即可
编写方法
/**
* 用户退出登录
* @param session
* @return
*/
@PostMapping("/loginout")
public R<String > logOut( HttpServletRequest session){
log.info("用户退出登录session:{}",session);
session.getSession().removeAttribute("user");
return R.success("退出成功");
}
8、客户端——购物车商品减少
前端请求分析
- 从前端请求可以看到参数传递的形式为JSON,所以后端我们用
ShoppingCart
实体类接收参数
编写方法
-
service层
/** * 购物车修改 * @param shoppingCart * @return */ public ShoppingCart sub(@RequestBody ShoppingCart shoppingCart);
-
impl层
/** * 购物车修改 * @param shoppingCart * @return */ @Override public ShoppingCart sub( ShoppingCart shoppingCart ) { //获取用户ID Long userId = BaseContext.getCurrentId(); //获取菜品ID Long dishId = shoppingCart.getDishId(); ShoppingCart one=null; //条件构造器 LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>(); //指定是哪个用户的购物车 queryWrapper.eq(ShoppingCart::getUserId,userId); if (dishId!=null){ //修改的是菜品数量 queryWrapper.eq(ShoppingCart::getDishId,dishId); one = this.getOne(queryWrapper); }else{ //修改的是套餐数量 queryWrapper.eq(ShoppingCart::getSetmealId,shoppingCart.getSetmealId()); one = this.getOne(queryWrapper); } //如果购物车中的数量大于1份,则相应的套餐数量减一 one.setNumber(one.getNumber()-1); if(one.getNumber()>0){ //如果还有套餐则更新数据 this.updateById(one); }else{ //如果购物中数量为0则删除 this.removeById(one); } return one; }
-
controller层
/** * 购物车修改 * @param shoppingCart * @return */ @PostMapping("/sub") public R<ShoppingCart> sub(@RequestBody ShoppingCart shoppingCart){ log.info("购物车修改shoppingCart:{}",shoppingCart); ShoppingCart one = shoppingCartService.sub(shoppingCart); return R.success(one); }
9、客户端——查看订单
前端请求分析
- 请求中带有两个参数,后端需要接收
准备工作
在编写方法前,需要导入 OrdersDto
编写方法
/**
* 用户最近订单查询
* @param page
* @param pageSize
* @return
*/
@GetMapping("/userPage")
public R<Page<Orders>> userPage( int page, int pageSize ){
log.info("用户订单分页");
//获取用户ID
Long userID = BaseContext.getCurrentId();
//分页构造器
Page<Orders> pageInfo = new Page<>(page,pageSize);
//条件构造器
LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
//指定用户的订单
queryWrapper.eq(Orders::getUserId,userID);
//添加排序条件
queryWrapper.orderByDesc(Orders::getOrderTime);
ordersService.page(pageInfo,queryWrapper);
return R.success(pageInfo);
}
运行结果
10、客户端——订单完成后再来一单
前端请求分析
-
当订单完成时可以选择买一个最近相同菜品/套餐
-
分析前端请求可知,该请求中带有一个参数,我们后端可以使用
Orders
实体类接收参数
编写方法
-
service层
/** * 再来一单 * @param orders */ public void again(Orders orders);
-
impl层
/** * 再来一单 * @param orders */ @Override public void again( Orders orders ) { //条件构造器 LambdaQueryWrapper<Orders> ordersLambdaQueryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<OrderDetail> orderDetailLambdaQueryWrapper = new LambdaQueryWrapper<>(); //添加订单ID条件 ordersLambdaQueryWrapper.eq(Orders::getId,orders.getId()); //添加指定订单的订单明细条件 orderDetailLambdaQueryWrapper.eq(OrderDetail::getOrderId,orders.getId()); //获取订单 Orders one = this.getOne(ordersLambdaQueryWrapper); //获取订单明细 List<OrderDetail> orderDetails = orderDetailService.list(orderDetailLambdaQueryWrapper); long orderId = IdWorker.getId();//订单号 //修改订单明细信息 orderDetails=orderDetails.stream().map((item)->{ item.setId(null); //移除原有的订单明细ID item.setOrderId(orderId); return item; }).collect(Collectors.toList()); //修改订单信息 one.setNumber(String.valueOf(orderId)); one.setId(orderId); one.setOrderTime(LocalDateTime.now()); one.setCheckoutTime(LocalDateTime.now()); one.setStatus(2); //向订单表插入一条数据 this.save(one); //向订单明细表插入数据,多条数据 orderDetailService.saveBatch(orderDetails); }
-
controller层
/** * 再来一单 * @param orders * @return */ @PostMapping("/again") public R<String> again(@RequestBody Orders orders){ log.info("再来一单orders:",orders); ordersService.again(orders); return R.success("再来一单成功"); }