• 瑞吉外卖 —— 8、菜品展示、购物车、下单


    目录

    1、用户地址簿 

    1.1、分析

    1.1.1、需求分析

    1.1.2、数据模型

    1.1.3、导入代码

    2、菜品展示

    2.1、分析

    2.1.1、需求分析 

    2.1.2、交互过程

    2.2、代码

    2.2.1、代码修改 

    2.2.2、获取套餐信息

    3、购物车

    3.1、分析

    3.1.1、需求分析

    3.1.2、数据模型

    3.1.3、交互过程

    3.2、代码

    3.2.1、向购物车添加菜品或套餐

    3.2.2、获取购物车信息

    3.2.3、清空购物车

    3.2.4、减少购物车菜品或套餐

    4、用户下单

    4.1、分析

    4.1.1、需求分析

    4.1.2、数据模型

    4.1.3、交互过程

    4.1.4、准备工作

    4.2、代码

    4.2.1、支付


    1、用户地址簿 

    1.1、分析

    1.1.1、需求分析

    1.1.2、数据模型

    用户的地址信息会存储在 address_book 表,即地址簿表中。具体表结构如下:

    1.1.3、导入代码

    2、菜品展示

    2.1、分析

    2.1.1、需求分析 

    2.1.2、交互过程

    2.2、代码

    2.2.1、代码修改 

    前端在初始化时发送上面的两次请求后,需要都成功才会渲染数据

    1. initData(){
    2. // 两次请求都成功蔡渲染页面
    3. Promise.all([categoryListApi(),cartListApi({})]).then(res=>{
    4. //获取分类数据
    5. if(res[0].code === 1){
    6. this.categoryList = res[0].data
    7. if(Array.isArray(res[0].data) && res[0].data.length > 0){
    8. this.categoryId = res[0].data[0].id
    9. if(res[0].data[0].type === 1){
    10. this.getDishList()
    11. }else{
    12. this.getSetmealData()
    13. }
    14. }
    15. }else{
    16. this.$notify({ type:'warning', message:res[0].msg});
    17. }
    18. //获取菜品数据
    19. if(res[1].code === 1){
    20. this.cartData = res[1].data
    21. }else{
    22. this.$notify({ type:'warning', message:res[1].msg});
    23. }
    24. })
    25. },

    所以将获取购物车的请求修改为获取假数据

    1. //获取购物车内商品的集合
    2. function cartListApi(data) {
    3. return $axios({
    4. // 'url': '/shoppingCart/list',
    5. 'url': '/front/cartData.json',
    6. 'method': 'get',
    7. params:{...data}
    8. })
    9. }

    假数据内容

    {"code":1,"msg":null,"data":[],"map":{}}

    修改完后便可以看到展示的菜品及图品,但没有其口味信息,因为 DishController 中的 list 方法返回的是 Dish 实体类,而 Dish 中没有口味属性,需要添加口味属性,要返回 DishDto

    1. /**
    2. * 根据条件查询菜品数据
    3. * @param dish
    4. * @return
    5. */
    6. /*@GetMapping("/list")
    7. public R> list(Dish dish){
    8. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    9. queryWrapper.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId());
    10. queryWrapper.eq(Dish::getStatus, 1);
    11. queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
    12. List list = dishSerivce.list(queryWrapper);
    13. return R.success(list);
    14. }*/
    15. @GetMapping("/list")
    16. public R> list(Dish dish){
    17. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    18. queryWrapper.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId());
    19. queryWrapper.eq(Dish::getStatus, 1);
    20. queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
    21. List list = dishSerivce.list(queryWrapper);
    22. List dishDtoList = list.stream().map((item) -> {
    23. DishDto dishDto = new DishDto();
    24. BeanUtils.copyProperties(item, dishDto);
    25. // 获取分类名称
    26. Long categoryId = item.getCategoryId();
    27. Category category = categoryService.getById(categoryId);
    28. if(category != null){
    29. String categoryName = category.getName();
    30. dishDto.setCategoryName(categoryName);
    31. }
    32. // 获取口味信息
    33. Long dishId = item.getId();
    34. LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
    35. wrapper.eq(DishFlavor::getDishId, dishId);
    36. List dishFlavorList = dishFlavorService.list(wrapper);
    37. dishDto.setFlavors(dishFlavorList);
    38. return dishDto;
    39. }).collect(Collectors.toList());
    40. return R.success(dishDtoList);
    41. }

    2.2.2、获取套餐信息

    请求:

    在 SetmealController 中添加方法

    1. /**
    2. * 根据条件获取套餐数据
    3. * @param setmeal
    4. * @return
    5. */
    6. @GetMapping("/list")
    7. public R> list(Setmeal setmeal){
    8. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    9. queryWrapper.eq(setmeal.getCategoryId() != null, Setmeal::getCategoryId, setmeal.getCategoryId());
    10. queryWrapper.eq(setmeal.getStatus() != null, Setmeal::getStatus, setmeal.getStatus());
    11. queryWrapper.orderByDesc(Setmeal::getUpdateTime);
    12. List list = setmealService.list(queryWrapper);
    13. return R.success(list);
    14. }

    3、购物车

    3.1、分析

    3.1.1、需求分析

    3.1.2、数据模型

    购物车对应的数据表为 shopping_cart 表,具体表结构如下:

    3.1.3、交互过程

    3.1.4、准备工作

     将获取购物车信息的代码改回来

    3.2、代码

    3.2.1、向购物车添加菜品或套餐

     添加菜品请求:

    添加套餐请求:

    在 ShoppingCartController 添加方法

    1. /**
    2. * 向购物车添加菜品或套餐
    3. * @param shoppingCart
    4. * @return
    5. */
    6. @PostMapping("/add")
    7. public R add(@RequestBody ShoppingCart shoppingCart){
    8. // 设置用户id,指定当前是哪个用户的购物车数据
    9. Long currentId = BaseContext.getCurrentId();
    10. shoppingCart.setUserId(currentId);
    11. // 查询当前菜品或套餐是否在购物车中
    12. Long dishId = shoppingCart.getDishId();
    13. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    14. queryWrapper.eq(ShoppingCart::getUserId, currentId);
    15. if(dishId != null){
    16. // 添加到购物车的是菜品
    17. queryWrapper.eq(ShoppingCart::getDishId, dishId);
    18. } else {
    19. // 添加到购物车的是套餐
    20. queryWrapper.eq(ShoppingCart::getSetmealId, shoppingCart.getSetmealId());
    21. }
    22. ShoppingCart cart = shoppingCartService.getOne(queryWrapper);
    23. if(cart != null){
    24. // 如果已存在,在原来的数量上加一
    25. cart.setNumber(cart.getNumber() + 1);
    26. shoppingCartService.updateById(cart);
    27. } else {
    28. // 如果不存在,则添加到购物车,默认数量为1
    29. shoppingCart.setNumber(1);
    30. shoppingCart.setCreateTime(LocalDateTime.now());
    31. shoppingCartService.save(shoppingCart);
    32. cart = shoppingCart;
    33. }
    34. return R.success(cart);
    35. }

    3.2.2、获取购物车信息

     获取购物车信息的请求:

    在 ShoppingCartController 添加方法

    1. /**
    2. * 查看购物车
    3. * @return
    4. */
    5. @GetMapping("/list")
    6. public R> list(){
    7. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    8. queryWrapper.eq(ShoppingCart::getUserId, BaseContext.getCurrentId());
    9. queryWrapper.orderByAsc(ShoppingCart::getCreateTime);
    10. List list = shoppingCartService.list(queryWrapper);
    11. return R.success(list);
    12. }

    3.2.3、清空购物车

    清空购物车请求:

    在 ShoppingCartController 添加方法 

    1. /**
    2. * 清空购物车
    3. * @return
    4. */
    5. @DeleteMapping("/clean")
    6. public R clean(){
    7. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    8. queryWrapper.eq(ShoppingCart::getUserId, BaseContext.getCurrentId());
    9. shoppingCartService.remove(queryWrapper);
    10. return R.success("清空购物车成功");
    11. }

    3.2.4、减少购物车菜品或套餐

    请求:

    1. /**
    2. * 减少购物车菜品或套餐
    3. * @return
    4. */
    5. @PostMapping("/sub")
    6. public R sub(@RequestBody ShoppingCart shoppingCart){
    7. Long currentId = BaseContext.getCurrentId();
    8. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    9. queryWrapper.eq(ShoppingCart::getUserId, currentId);
    10. ShoppingCart cart = null;
    11. // 获取要减少的菜品或套餐信息
    12. Long dishId = shoppingCart.getDishId();
    13. if(dishId == null){
    14. // 减少的是套餐数量
    15. Long setmealId = shoppingCart.getSetmealId();
    16. queryWrapper.eq(ShoppingCart::getSetmealId, setmealId);
    17. cart = shoppingCartService.getOne(queryWrapper);
    18. } else {
    19. // 减少的是菜品数量
    20. queryWrapper.eq(ShoppingCart::getDishId, dishId);
    21. cart = shoppingCartService.getOne(queryWrapper);
    22. }
    23. Integer number = cart.getNumber();
    24. if(number > 1){
    25. cart.setNumber(number - 1);
    26. shoppingCartService.updateById(cart);
    27. } else {
    28. shoppingCartService.removeById(cart.getId());
    29. }
    30. return R.success(cart);
    31. }

    4、用户下单

    4.1、分析

    4.1.1、需求分析

    4.1.2、数据模型

    用户下单业务对应的数据表为 orders 表和 order_detail 表:

    orders 表:

    order_detail 表

    4.1.3、交互过程

    4.1.4、准备工作

    4.2、代码

    4.2.1、支付

    支付请求:

    ① 在 OrderServiceImpl 实现方法

    1. package com.itheima.reggie.service.impl;
    2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    3. import com.baomidou.mybatisplus.core.toolkit.IdWorker;
    4. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    5. import com.itheima.reggie.common.BaseContext;
    6. import com.itheima.reggie.common.CustomException;
    7. import com.itheima.reggie.entity.*;
    8. import com.itheima.reggie.mapper.OrderMapper;
    9. import com.itheima.reggie.service.*;
    10. import lombok.extern.slf4j.Slf4j;
    11. import org.springframework.beans.factory.annotation.Autowired;
    12. import org.springframework.stereotype.Service;
    13. import org.springframework.transaction.annotation.Transactional;
    14. import java.math.BigDecimal;
    15. import java.time.LocalDateTime;
    16. import java.util.List;
    17. import java.util.concurrent.atomic.AtomicInteger;
    18. import java.util.stream.Collectors;
    19. @Service
    20. @Slf4j
    21. public class OrderServiceImpl extends ServiceImpl implements OrderService {
    22. @Autowired
    23. private ShoppingCartService shoppingCartService;
    24. @Autowired
    25. private UserService userService;
    26. @Autowired
    27. private AddressBookService addressBookService;
    28. @Autowired
    29. private OrderDetailService orderDetailService;
    30. /**
    31. * 用户下单
    32. * @param orders
    33. */
    34. @Transactional
    35. public void submit(Orders orders) {
    36. //获得当前用户id
    37. Long userId = BaseContext.getCurrentId();
    38. // 查询当前用户的购物车数据
    39. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    40. queryWrapper.eq(ShoppingCart::getUserId, userId);
    41. List shoppingCarts = shoppingCartService.list(queryWrapper);
    42. if(shoppingCarts == null || shoppingCarts.size() == 0){
    43. throw new CustomException("购物车为空,无法下单");
    44. }
    45. // 查询用户数据
    46. User user = userService.getById(userId);
    47. // 查询地址信息
    48. AddressBook addressBook = addressBookService.getById(orders.getAddressBookId());
    49. if(addressBook == null){
    50. throw new CustomException("用户地址信息有误,无法下单");
    51. }
    52. // 生成订单号
    53. long orderId = IdWorker.getId();
    54. // 计算订单总金额
    55. AtomicInteger amount = new AtomicInteger(0); // 保证线程安全
    56. List orderDetails = shoppingCarts.stream().map((item) -> {
    57. OrderDetail orderDetail = new OrderDetail();
    58. orderDetail.setOrderId(orderId);
    59. orderDetail.setNumber(item.getNumber());
    60. orderDetail.setDishFlavor(item.getDishFlavor());
    61. orderDetail.setDishId(item.getDishId());
    62. orderDetail.setSetmealId(item.getSetmealId());
    63. orderDetail.setName(item.getName());
    64. orderDetail.setImage(item.getImage());
    65. orderDetail.setAmount(item.getAmount());
    66. amount.addAndGet(item.getAmount().multiply(new BigDecimal(item.getNumber())).intValue()); // +=
    67. return orderDetail;
    68. }).collect(Collectors.toList());
    69. // 向订单表插入数据
    70. orders.setId(orderId);
    71. orders.setOrderTime(LocalDateTime.now());
    72. orders.setCheckoutTime(LocalDateTime.now());
    73. orders.setStatus(2);
    74. orders.setAmount(new BigDecimal(amount.get())); //总金额
    75. orders.setUserId(userId);
    76. orders.setNumber(String.valueOf(orderId));
    77. orders.setUserName(user.getName());
    78. orders.setConsignee(addressBook.getConsignee());
    79. orders.setPhone(addressBook.getPhone());
    80. orders.setAddress((addressBook.getProvinceName() == null ? "" : addressBook.getProvinceName())
    81. + (addressBook.getCityName() == null ? "" : addressBook.getCityName())
    82. + (addressBook.getDistrictName() == null ? "" : addressBook.getDistrictName())
    83. + (addressBook.getDetail() == null ? "" : addressBook.getDetail()));
    84. this.save(orders);
    85. // 向订单明细表插入数据(多条数据)
    86. orderDetailService.saveBatch(orderDetails);
    87. // 清空购物车数据
    88. shoppingCartService.remove(queryWrapper);
    89. }
    90. }

    ② 在 OrderController 中使用方法

    1. /**
    2. * 支付订单
    3. * @param orders
    4. * @return
    5. */
    6. @PostMapping("/submit")
    7. public R submit(@RequestBody Orders orders){
    8. orderService.submit(orders);
    9. return null;
    10. }

  • 相关阅读:
    git 合并两个不同仓库
    UVM寄存器模型:reg adapter实现和集成
    一些思想概念(分布式 )
    产品经理与项目经理的区别?
    【Hack The Box】windows练习-- Object
    【python基础】if语句-语法格式
    【每日一题】打卡 55
    【CSDN】markdown实用语法
    云原生之Kubernetes:16、详解Operator控制器
    Hadoop-Hive-Spark-离线环境搭建
  • 原文地址:https://blog.csdn.net/Mr_zhangyj/article/details/126700375