整理记录下学习整个瑞吉外卖项目,详细代码可在我的Gitee仓库瑞吉外卖实战克隆下载学习使用!

12.菜品展示

12.1 需求分析

12.2 更改前台页面使其正常显示

由于购物车功能还未进行开发,所以修改main.js中的cartListJson函数中访问固定数据,如图

重启清除缓存后如图

12.3 修改查询菜品方法

12.3.1 代码开发

前台访问的是查询菜品接口方法list,但移动端还需要菜品的口味信息,所以必须得修改DishController中原有的方法,修改如下:

    @GetMapping("/list")  public Result<List<DishDto>> list(Dish dish) {  List<DishDto> dishDtoList;  //构造查询条件  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);  dishDtoList = list.stream().map((item) -> {  DishDto dishDto = new DishDto();  BeanUtils.copyProperties(item, dishDto);  Long categoryId = item.getCategoryId();//分类id  //当前菜品的id  Long dishId = item.getId();  LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();  lambdaQueryWrapper.eq(DishFlavor::getDishId, dishId);  //SQL:select * from dish_flavor where dish_id = ?  List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);  dishDto.setFlavors(dishFlavorList);  return dishDto;  }).collect(Collectors.toList());  return Result.success(dishDtoList);  }

12.3.2 测试

  • 测试后如图,点击添加规格有口味信息来选择

12.4 查询套餐

12.4.1 代码开发

SetmealController编写查询套餐代码,如下:

@GetMapping("/list")  public Result<List<Setmeal>> list(Setmeal setmeal) {  LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();  queryWrapper.eq(setmeal.getCategoryId() != null, Setmeal::getCategoryId, setmeal.getCategoryId());  queryWrapper.eq(setmeal.getStatus() != null, Setmeal::getStatus, setmeal.getStatus());  queryWrapper.orderByDesc(Setmeal::getUpdateTime);  List<Setmeal> list = setmealService.list(queryWrapper);  return Result.success(list);  }

12.4.2 测试

如图所示,不再报错

13. 购物车模块

13.1需求分析

13.2 数据模型

购物车对应表为shopping_cart表,结构如下:

13.3 代码开发

13.3.1 导入实体类或编写实体类

@Data
public class ShoppingCart implements Serializable {  private static final long serialVersionUID = 1L;  private Long id;  //名称  private String name;  //用户id  private Long userId;  //菜品id  private Long dishId;  //套餐id  private Long setmealId;  //口味  private String dishFlavor;  //数量  private Integer number;  //金额  private BigDecimal amount;  //图片  private String image;  private LocalDateTime createTime;
}

13.3.2 新建对应的Mapper、Service及实现类和controller类

这里自行建立就行,和之前一样

13.3.3 购物车添加功能

  • controller编写添加功能,如下:
@Slf4j
@RestController
@RequestMapping("/shoppingCart")
@RequiredArgsConstructor
public class ShoppingCartController {  private final ShoppingCartService shoppingCartService;  /**  * 添加购物车  * @param shoppingCart  * @return  */  @PostMapping("/add")  public Result<ShoppingCart> add(@RequestBody ShoppingCart shoppingCart){  log.info("购物车数据:{}",shoppingCart);  //设置用户id,指定当前是哪个用户的购物车数据  Long currentId = BaseContext.getCurrentId();  shoppingCart.setUserId(currentId);  Long dishId = shoppingCart.getDishId();  LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();  queryWrapper.eq(ShoppingCart::getUserId,currentId);  if(dishId != null){  //添加到购物车的是菜品  queryWrapper.eq(ShoppingCart::getDishId,dishId);  }else{  //添加到购物车的是套餐  queryWrapper.eq(ShoppingCart::getSetmealId,shoppingCart.getSetmealId());  }  //查询当前菜品或者套餐是否在购物车中  //SQL:select * from shopping_cart where user_id = ? and dish_id/setmeal_id = ?  ShoppingCart cartServiceOne = shoppingCartService.getOne(queryWrapper);  if(cartServiceOne != null){  //如果已经存在,就在原来数量基础上加一  Integer number = cartServiceOne.getNumber();  cartServiceOne.setNumber(number + 1);  shoppingCartService.updateById(cartServiceOne);  }else{  //如果不存在,则添加到购物车,数量默认就是一  shoppingCart.setNumber(1);  shoppingCart.setCreateTime(LocalDateTime.now());  shoppingCartService.save(shoppingCart);  cartServiceOne = shoppingCart;  }  return Result.success(cartServiceOne);  }}

13.3.4 测试

测试添加功能,如图操作
数据库查看结果

13.3.5 购物车查看

  • 更改main.js为原来,如图
  • 编写查看方法,如下:
@GetMapping("/list")
public Result<List<ShoppingCart>> list(){  log.info("查看购物车...");  LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();  queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());  queryWrapper.orderByAsc(ShoppingCart::getCreateTime);  List<ShoppingCart> list = shoppingCartService.list(queryWrapper);  return Result.success(list);
}

13.3.6 测试

测试,登录之前账号查看,如图

13.3.7 购物车套餐或菜品数量减少

  • 编写减少方法,如下:
@PostMapping("/sub")
public Result<ShoppingCart> sub(@RequestBody ShoppingCart shoppingCart) {  Long dishId = shoppingCart.getDishId();  Long setmealId = shoppingCart.getSetmealId();  //条件构造器  LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();  //只查询当前用户ID的购物车  queryWrapper.eq(ShoppingCart::getUserId, BaseContext.getCurrentId());  //代表数量减少的是菜品数量  if (dishId != null) {  //通过dishId查出购物车菜品数据  queryWrapper.eq(ShoppingCart::getDishId, dishId);  ShoppingCart dishCart = shoppingCartService.getOne(queryWrapper);  //将查出来的数据的数量-1  dishCart.setNumber(dishCart.getNumber() - 1);  Integer currentNum = dishCart.getNumber();  //然后判断  if (currentNum > 0) {  //大于0则更新  shoppingCartService.updateById(dishCart);  } else if (currentNum == 0) {  //小于0则删除  shoppingCartService.removeById(dishCart.getId());  }  return Result.success(dishCart);  }  if (setmealId != null) {  //通过setmealId查询购物车套餐数据  queryWrapper.eq(ShoppingCart::getSetmealId, setmealId);  ShoppingCart setmealCart = shoppingCartService.getOne(queryWrapper);  //将查出来的数据的数量-1  setmealCart.setNumber(setmealCart.getNumber() - 1);  Integer currentNum = setmealCart.getNumber();  //然后判断  if (currentNum > 0) {  //大于0则更新  shoppingCartService.updateById(setmealCart);  } else if (currentNum == 0) {  //等于0则删除  shoppingCartService.removeById(setmealCart.getId());  }  return Result.success(setmealCart);  }  return Result.error("系统繁忙,请稍后再试");
}
  • 测试,再次登录之前账号,点击+号结果如图,添加成功

    点击-号,如图
    数据库结果正确

13.3.8 购物车清空

@DeleteMapping("/clean")
public Result<String> clean(){  //SQL:delete from shopping_cart where user_id = ?  LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();  queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());  shoppingCartService.remove(queryWrapper);  return Result.success("清空购物车成功");
}

13.3.9 测试

再次登录之前账号,点击清空,结果如图

14. 用户下单

14.1 需求分析

14.2 数据模型

涉及到两张表orders表和order-detials表,结构如图
- 订单表orders,如图
- 订单详情表order_details,如图

14.3 代码开发

14.3.1 编写导入实体类

@Data
public class Orders implements Serializable {  private static final long serialVersionUID = 1L;  private Long id;  //订单号  private String number;  //订单状态 1待付款,2待派送,3已派送,4已完成,5已取消  private Integer status;  //下单用户id  private Long userId;  //地址id  private Long addressBookId;  //下单时间  private LocalDateTime orderTime;  //结账时间  private LocalDateTime checkoutTime;  //支付方式 1微信,2支付宝  private Integer payMethod;  //实收金额  private BigDecimal amount;  //备注  private String remark;  //用户名  private String userName;  //手机号  private String phone;  //地址  private String address;  //收货人  private String consignee;
}//订单详情类
@Data
public class OrderDetail implements Serializable {  private static final long serialVersionUID = 1L;  private Long id;  //名称  private String name;  //订单id  private Long orderId;  //菜品id  private Long dishId;  //套餐id  private Long setmealId;  //口味  private String dishFlavor;  //数量  private Integer number;  //金额  private BigDecimal amount;  //图片  private String image;
}

14.3.2 新建对应的Mapper、Service及实现类

和之前一样

14.3.3 添加数据传输对象OrdersDto

用于将订单和对应的订单详情结合在一个类里,代码如下:

@Data
public class OrdersDto extends Orders {  private List<OrderDetail> orderDetails;
}

14.3.4 编写提交订单业务

OrderService加入submit方法并进行实现。代码如下:

@Service
@Slf4j
@RequiredArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService {  private final ShoppingCartService shoppingCartService;  private final UserService userService;  private final AddressBookService addressBookService;  private final OrderDetailService orderDetailService;  /**  * 用户下单  * @param orders  */  @Transactional  public void submit(Orders orders) {  //获得当前用户id  Long userId = BaseContext.getCurrentId();  //查询当前用户的购物车数据  LambdaQueryWrapper<ShoppingCart> wrapper = new LambdaQueryWrapper<>();  wrapper.eq(ShoppingCart::getUserId,userId);  List<ShoppingCart> shoppingCarts = shoppingCartService.list(wrapper);  if(shoppingCarts == null || shoppingCarts.size() == 0){  throw new CustomException("购物车为空,不能下单");  }  //查询用户数据  User user = userService.getById(userId);  //查询地址数据  Long addressBookId = orders.getAddressBookId();  AddressBook addressBook = addressBookService.getById(addressBookId);  if(addressBook == null){  throw new CustomException("用户地址信息有误,不能下单");  }  long orderId = IdWorker.getId();//订单号  AtomicInteger amount = new AtomicInteger(0);  List<OrderDetail> orderDetails = shoppingCarts.stream().map((item) -> {  OrderDetail orderDetail = new OrderDetail();  orderDetail.setOrderId(orderId);  orderDetail.setNumber(item.getNumber());  orderDetail.setDishFlavor(item.getDishFlavor());  orderDetail.setDishId(item.getDishId());  orderDetail.setSetmealId(item.getSetmealId());  orderDetail.setName(item.getName());  orderDetail.setImage(item.getImage());  orderDetail.setAmount(item.getAmount());  amount.addAndGet(item.getAmount().multiply(new BigDecimal(item.getNumber())).intValue());  return orderDetail;  }).collect(Collectors.toList());  orders.setId(orderId);  orders.setOrderTime(LocalDateTime.now());  orders.setCheckoutTime(LocalDateTime.now());  orders.setStatus(2);  orders.setAmount(new BigDecimal(amount.get()));//总金额  orders.setUserId(userId);  orders.setNumber(String.valueOf(orderId));  orders.setUserName(user.getName());  orders.setConsignee(addressBook.getConsignee());  orders.setPhone(addressBook.getPhone());  orders.setAddress((addressBook.getProvinceName() == null ? "" : addressBook.getProvinceName())  + (addressBook.getCityName() == null ? "" : addressBook.getCityName())  + (addressBook.getDistrictName() == null ? "" : addressBook.getDistrictName())  + (addressBook.getDetail() == null ? "" : addressBook.getDetail()));  //向订单表插入数据,一条数据  this.save(orders);  //向订单明细表插入数据,多条数据  orderDetailService.saveBatch(orderDetails);  //清空购物车数据  shoppingCartService.remove(wrapper);  }
}

14.3.5 编写Controller类

controller层调用提交订单方法即可,如图

14.4 测试

启动项目后,登录之前的账号,点击结算后填写地址并设置为默认地址,如图
再次点击结算后跳转到支付页面,如图
支付成功后如图

15. 历史订单

15.1需求分析

  • 当用户想再次点购上次吃的菜品或套餐时可以通过查看历史订单来知道
  • 当用户下单后管理员必须进行相应的操作,派送或者查看订单详情

15.2 代码开发

  • 直接在OrdesController类中编写查找历史订单,修改订单状态及查看订单方法,如下:
@GetMapping("/userPage")
public Result<Page> page(int page, int pageSize) {  //获取当前id  Long userId = BaseContext.getCurrentId();  Page<Orders> pageInfo = new Page<>(page, pageSize);  Page<OrdersDto> ordersDtoPage = new Page<>(page, pageSize);  //条件构造器  LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();  //查询当前用户id订单数据  queryWrapper.eq(userId != null, Orders::getUserId, userId);  //按时间降序排序  queryWrapper.orderByDesc(Orders::getOrderTime);  orderService.page(pageInfo, queryWrapper);  List<OrdersDto> list = pageInfo.getRecords().stream().map((item) -> {  OrdersDto ordersDto = new OrdersDto();  //获取orderId,然后根据这个id,去orderDetail表中查数据  Long orderId = item.getId();  LambdaQueryWrapper<OrderDetail> wrapper = new LambdaQueryWrapper<>();  wrapper.eq(OrderDetail::getOrderId, orderId);  List<OrderDetail> details = orderDetailService.list(wrapper);  BeanUtils.copyProperties(item, ordersDto);  //之后set一下属性  ordersDto.setOrderDetails(details);  return ordersDto;  }).collect(Collectors.toList());  BeanUtils.copyProperties(pageInfo, ordersDtoPage, "records");  ordersDtoPage.setRecords(list);  //日志输出看一下  log.info("list:{}", list);  return Result.success(ordersDtoPage);
}
@PostMapping("/again")
public Result<String> again(@RequestBody Map<String,String> map){  //获取order_id  Long orderId = Long.valueOf(map.get("id"));  //条件构造器  LambdaQueryWrapper<OrderDetail> queryWrapper = new LambdaQueryWrapper<>();  //查询订单的口味细节数据  queryWrapper.eq(OrderDetail::getOrderId,orderId);  List<OrderDetail> details = orderDetailService.list(queryWrapper);  //获取用户id,待会需要set操作  Long userId = BaseContext.getCurrentId();  List<ShoppingCart> shoppingCarts = details.stream().map((item) ->{  ShoppingCart shoppingCart = new ShoppingCart();  //Copy对应属性值  BeanUtils.copyProperties(item,shoppingCart);  //设置一下userId  shoppingCart.setUserId(userId);  //设置一下创建时间为当前时间  shoppingCart.setCreateTime(LocalDateTime.now());  return shoppingCart;  }).collect(Collectors.toList());  //加入购物车  shoppingCartService.saveBatch(shoppingCarts);  return Result.success("喜欢吃就再来一单吖~");
}
/**  * 订单明细  * @param page  * @param pageSize  * @param number  * @param beginTime  * @param endTime  * @return  */
@GetMapping("/page")
public Result<Page> page(int page, int pageSize, Long number, String beginTime, String endTime) {  //获取当前id  Page<Orders> pageInfo = new Page<>(page, pageSize);  Page<OrdersDto> ordersDtoPage = new Page<>(page, pageSize);  //条件构造器  LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();  //按时间降序排序  queryWrapper.orderByDesc(Orders::getOrderTime);  //订单号  queryWrapper.eq(number != null, Orders::getId, number);  //时间段,大于开始,小于结束  queryWrapper.gt(!StringUtils.isEmpty(beginTime), Orders::getOrderTime, beginTime)  .lt(!StringUtils.isEmpty(endTime), Orders::getOrderTime, endTime);  orderService.page(pageInfo, queryWrapper);  List<OrdersDto> list = pageInfo.getRecords().stream().map((item) -> {  OrdersDto ordersDto = new OrdersDto();  //获取orderId,然后根据这个id,去orderDetail表中查数据  Long orderId = item.getId();  LambdaQueryWrapper<OrderDetail> wrapper = new LambdaQueryWrapper<>();  wrapper.eq(OrderDetail::getOrderId, orderId);  List<OrderDetail> details = orderDetailService.list(wrapper);  BeanUtils.copyProperties(item, ordersDto);  //之后set一下属性  ordersDto.setOrderDetails(details);  return ordersDto;  }).collect(Collectors.toList());  BeanUtils.copyProperties(pageInfo, ordersDtoPage, "records");  ordersDtoPage.setRecords(list);  //日志输出看一下  log.info("list:{}", list);  return Result.success(ordersDtoPage);
}  @PutMapping
public Result<String> changeStatus(@RequestBody Map<String, String> map) {  int status = Integer.parseInt(map.get("status"));  Long orderId = Long.valueOf(map.get("id"));  log.info("修改订单状态:status={status},id={id}", status, orderId);  LambdaUpdateWrapper<Orders> updateWrapper = new LambdaUpdateWrapper<>();  updateWrapper.eq(Orders::getId, orderId);  updateWrapper.set(Orders::getStatus, status);  orderService.update(updateWrapper);  return Result.success("订单状态修改成功");
}

15.3 测试

  • 还是登录之前账号,点击头像后选择历史订单,结果如图
  • 后台登录管理员进行点击派送,如图

    显示订单派送完成,如图
  • 点击完成订单,如图
    显示
  • 点击查看订单详情后如图
  • 输入订单号进行查询后,如图

瑞吉外卖-移动端菜品展示功能,购物车添加菜品及修改等功能,用户下单功能及历史订单派送功能相关推荐

  1. 猿创征文|瑞吉外卖——管理端_菜品管理_1

    个人名片: 博主:酒徒ᝰ. 专栏:瑞吉外卖 个人简介:沉醉在酒中,借着一股酒劲,去拼搏一个未来. 本篇励志:真正的程序员不看参考手册,新手和胆小鬼才会看. 本项目基于B站黑马程序员Java项目实战&l ...

  2. 猿创征文|瑞吉外卖——移动端_订单明细

    个人名片: 博主:酒徒ᝰ. 专栏:瑞吉外卖 个人简介:沉醉在酒中,借着一股酒劲,去拼搏一个未来. 本篇励志:一些伤口之所以总会痛,那是因为你总是去摸.有一种女人像贝壳一样,外面很硬,内在其实很软.心里 ...

  3. 猿创征文|瑞吉外卖——移动端_邮箱验证码登录

    个人名片: 博主:酒徒ᝰ. 专栏:瑞吉外卖 个人简介:沉醉在酒中,借着一股酒劲,去拼搏一个未来. 本篇励志:如果决意去做一件事了就不要再问自己和别人值不值得. 本项目基于B站黑马程序员Java项目实战 ...

  4. 猿创征文|瑞吉外卖——移动端_购物车

    个人名片: 博主:酒徒ᝰ. 专栏:瑞吉外卖 个人简介:沉醉在酒中,借着一股酒劲,去拼搏一个未来. 本篇励志:一份耕耘,一份收获.眼要看远,脚要近迈.在强者的眼中,没有最好,只有更好.向竞争挑战,向压力 ...

  5. 猿创征文|瑞吉外卖——管理端_订单明细

    个人名片: 博主:酒徒ᝰ. 专栏:瑞吉外卖 个人简介:沉醉在酒中,借着一股酒劲,去拼搏一个未来. 本篇励志:一个人静静坐在电脑面前写代码的感觉,那是什么感觉?那是武林高手闭关修炼的感觉. 本项目基于B ...

  6. 猿创征文|瑞吉外卖——移动端_地址管理

    个人名片: 博主:酒徒ᝰ. 专栏:瑞吉外卖 个人简介:沉醉在酒中,借着一股酒劲,去拼搏一个未来. 本篇励志:人会想很多事,而且多半是痛苦的,时光如水,我们无法阻止岁月的脚步,很多人,逐渐淡出了我们的视 ...

  7. 【瑞吉外卖】学习笔记-day4:(三)菜品管理开发——菜品信息分页查询、修改菜品、停售起售菜品以及删除菜品

    菜品信息分页查询: 需求分析: 系统中的菜品数据很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看,所以一般的系统中都会以分页的方式来展示列表数据. 其中,图片列和菜品分类列比较特殊.图 ...

  8. 瑞吉外卖之移动端菜品数据的展示

    瑞吉外卖之移动端菜品数据的展示 界面分析 界面分析 上篇我们主要完成了了瑞吉外卖移动端界面登录的功能.完成界面登录自然要进入主界面. 我们和前面的登录界面进行衔接上. 于是我们跳转到这个界面,也就是我 ...

  9. SB_5_瑞吉外卖_4_文件上传下载_菜品新增_菜品分页查询_菜品修改

    瑞吉外卖-Day04 课程内容 文件上传下载 菜品新增 菜品分页查询 菜品修改 1. 文件上传下载 1.1 上传介绍 1.1.1 概述 文件上传,也称为upload,是指将本地图片.视频.音频等文件上 ...

最新文章

  1. 我翻译的一篇文章,OO设计中对象的创建和使用
  2. 好玩,新版微信除了“炸屎”,还可以和她亲亲
  3. Linux多任务编程——进程
  4. linux缓存文件用户权限错误,CVE-2019-11244漏洞到底该如何修复?--关于缓存文件权限设置...
  5. java 系统类型_Java获取操作系统类型
  6. ueditor 上传视频丢失src的解决方法
  7. 对老年人友好!滴滴开通打车400热线
  8. 局域网中只有一台电脑无法连接共享打印机,其他电脑均可正常连接解决方案
  9. Hyper-V 测试
  10. 【电大题酷】【5】2269个人与团队管理
  11. 【OpenCV】计算两幅图片视觉差
  12. 微软重新评估收购雅虎提议
  13. uniapp 判断是否登录,是跳转至首页,否跳转至登录页
  14. 苹果主题商店_苹果tf签名上架需要使用什么材料?
  15. java调用阿里云api发送短信验证服务
  16. Python魔方方法详解
  17. Java实现 LeetCode 520 检测大写字母
  18. c语言万年历闹钟程序,C语言万年历的源程序
  19. (ios 5.1).html,iOS 5.1.1完美越狱教程(使用Absinthe 2.0.1)
  20. 文件默认保存位置无法使用 将不能正常使用微信,如何解决?

热门文章

  1. (xml+flash)flash播放器代码!
  2. 成功解决:java.util.LinkedHashMap cannot be cast to com.zyz.bookshopmanage.pojo.GoodsInfo
  3. oracle crs的管理,crs之上resource管理命令介绍
  4. 子进程信号继承;kill+raise+alarm+pause+信号发生接收和处理+信号屏蔽
  5. 如何像学霸一样高效学习?
  6. android百度地图的点击事件监听,百度地图监听事件addEventListener无效
  7. matlab模拟短波天波,天波传播.ppt
  8. 嵌入式软件内功修炼心法
  9. 科技赋能运动健身行业,为健身器材装上“智能芯”
  10. iOS-Core-Animation-Advanced-Techniques(七)