【瑞吉外卖 | day07】移动端菜品展示、购物车、下单

文章目录

  • [瑞吉外卖 --- day7](#瑞吉外卖 — day7)
    • [1. 导入用户地址簿相关功能代码](#1. 导入用户地址簿相关功能代码)
      • [1.1 需求分析](#1.1 需求分析)
      • [1.2 数据模型](#1.2 数据模型)
      • [1.3 代码开发](#1.3 代码开发)
    • [2. 菜品展示](#2. 菜品展示)
      • [2.1 需求分析](#2.1 需求分析)
      • [2.2 代码开发](#2.2 代码开发)
    • [3. 购物车](#3. 购物车)
      • [3.1 需求分析](#3.1 需求分析)
      • [3.2 数据模型](#3.2 数据模型)
      • [3.3 代码开发](#3.3 代码开发)
    • [4. 下单](#4. 下单)
      • [4.1 需求分析](#4.1 需求分析)
      • [4.2 数据模型](#4.2 数据模型)
      • [4.3 代码开发](#4.3 代码开发)

瑞吉外卖 --- day7

  • 移动端相关业务功能 ------ 菜品展示、购物车、下单

1. 导入用户地址簿相关功能代码

1.1 需求分析

  • 地址簿,指的是移动端消费者用户的地址信息,用户登录成功后可以维护自己的地址信息。同一个用户可以有多个地址信息,但是只能有一个默认地址

1.2 数据模型

  • 用户的地址信息会存储在address_book表,即地址簿表中。

1.3 代码开发

  • 导入功能代码

    实体类AddressBook(直接从课程资料中导入即可)

    Mapper接口AddressBookMapper

    业务层接口AddressBookService

    业务层实现类AddressBookServicelmpl

    控制层AddressBookController(直接从课程资料中导入即可)

  • AddressBookController代码

    java 复制代码
    /**
     * 地址簿管理
     */
    @Slf4j
    @RestController
    @RequestMapping("/addressBook")
    public class AddressBookController {
    
        @Autowired
        private AddressBookService addressBookService;
    
        /**
         * 新增
         */
        @PostMapping
        public R<AddressBook> save(@RequestBody AddressBook addressBook) {
            addressBook.setUserId(BaseContext.getCurrentId());
            log.info("addressBook:{}", addressBook);
            addressBookService.save(addressBook);
            return R.success(addressBook);
        }
    
        /**
         * 设置默认地址
         */
        @PutMapping("default")
        public R<AddressBook> setDefault(@RequestBody AddressBook addressBook) {
            log.info("addressBook:{}", addressBook);
            LambdaUpdateWrapper<AddressBook> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(AddressBook::getUserId, BaseContext.getCurrentId());
            wrapper.set(AddressBook::getIsDefault, 0);
            //SQL:update address_book set is_default = 0 where user_id = ?
            addressBookService.update(wrapper);
    
            addressBook.setIsDefault(1);
            //SQL:update address_book set is_default = 1 where id = ?
            addressBookService.updateById(addressBook);
            return R.success(addressBook);
        }
    
        /**
         * 根据id查询地址
         */
        @GetMapping("/{id}")
        public R get(@PathVariable Long id) {
            AddressBook addressBook = addressBookService.getById(id);
            if (addressBook != null) {
                return R.success(addressBook);
            } else {
                return R.error("没有找到该对象");
            }
        }
    
        /**
         * 查询默认地址
         */
        @GetMapping("default")
        public R<AddressBook> getDefault() {
            LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(AddressBook::getUserId, BaseContext.getCurrentId());
            queryWrapper.eq(AddressBook::getIsDefault, 1);
    
            //SQL:select * from address_book where user_id = ? and is_default = 1
            AddressBook addressBook = addressBookService.getOne(queryWrapper);
    
            if (null == addressBook) {
                return R.error("没有找到该对象");
            } else {
                return R.success(addressBook);
            }
        }
    
        /**
         * 查询指定用户的全部地址
         */
        @GetMapping("/list")
        public R<List<AddressBook>> list(AddressBook addressBook) {
            addressBook.setUserId(BaseContext.getCurrentId());
            log.info("addressBook:{}", addressBook);
    
            //条件构造器
            LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(null != addressBook.getUserId(), AddressBook::getUserId, addressBook.getUserId());
            queryWrapper.orderByDesc(AddressBook::getUpdateTime);
    
            //SQL:select * from address_book where user_id = ? order by update_time desc
            return R.success(addressBookService.list(queryWrapper));
        }
    }

2. 菜品展示

2.1 需求分析

  • 用户登录成功后跳转到系统首页,在首页需要根据分类来展示菜品和套餐
    。如果菜品设置了口味信息,需要展示洗择规格按钮,否则显示==+==按钮。

2.2 代码开发

  • 前端与服务端交互过程

    1、页面(front/index.html)发送ajax请求,获取分类数据(菜品分类和套餐分类)

    2、页面发送ajax请求,获取第一个分类下的菜品或者套餐

  • 页面(front/index.html)发送ajax请求,获取分类数据(菜品分类和套餐分类)

  • 页面发送ajax请求,获取第一个分类下的菜品或者套餐

    DishController中:

    java 复制代码
    @GetMapping("list")
        public R<List<DishDto>> 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);
    
            List<DishDto> dishDtoList = list.stream().map((item) -> {
                DishDto dishDto = new DishDto();
                BeanUtils.copyProperties(item,dishDto);
    
                Long categoryId = item.getCategoryId();
                //根据id查询分类对象
                Category category = categoryService.getById(categoryId);
    
                if(category != null){
                    String categoryName = category.getName();
                    dishDto.setCategoryName(categoryName);
                }
    
                //当前菜品的id
                Long dishId = item.getId();
                LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(DishFlavor::getDishId,dishId);
                List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);
                dishDto.setFlavors(dishFlavorList);
    
                return dishDto;
            }).collect(Collectors.toList());
    
            return R.success(dishDtoList);
        }

    SetmealController中:

    java 复制代码
    /**
         * 根据条件查询套餐数据
         * @param setmeal
         * @return
         */
        @GetMapping("list")
        public R<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 R.success(list);
        }

3. 购物车

3.1 需求分析

  • 移动端用户可以将菜品或者套餐添加到购物车。对于菜品来说,如果设置了口味信息,则需要选择规格后才能加入购物车;对于套餐来说,可以直接点击将当前套餐加入购物车。在购物车中可以修改菜品和套餐的数量,也可以清空购物车。

3.2 数据模型

  • 购物车对应的数据表为shopping_cart表

3.3 代码开发

  • 前段与服务端交互过程

    1、点击加入购物车或者+按钮,页面发送ajax请求,请求服务端,将菜品或者套餐添加到购物车

    2、点击购物车图标,页面发送ajax请求,请求服务端查询购物车中的菜品和套餐

    3、点击清空购物车按钮,页面发送ajax请求,请求服务端来执行清空购物车操作

  • 创建需要的类和接口

    实体类ShoppingCart ( 直接从课程资料中导入即可)

    Mapper接口ShoppingCartMapper

    业务层接口ShoppingCartService

    业务层实现类ShoppingCartServicelmpl

    控制层ShoppingCartController

  • 将菜品或者套餐添加到购物车

    java 复制代码
    @RestController
    @RequestMapping("shoppingCart")
    @Slf4j
    public class ShoppingCartController {
    
        @Autowired
        private ShoppingCartService shoppingCartService;
    
        /**
         * 添加购物车
         * @param shoppingCart
         * @return
         */
        @PostMapping("add")
        public R<ShoppingCart> add(@RequestBody ShoppingCart shoppingCart){
            log.info("购物车数据:{}",shoppingCart);
    
            //设置用户id,指定当前是哪个用户的购物车数据
            Long currentId = BaseContext.getCurrentId();
            shoppingCart.setUserId(currentId);
    
            LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ShoppingCart::getUserId,currentId);
    
            //查询当前菜品或套餐,是否在购物车中
            Long dishId = shoppingCart.getDishId();
            if(dishId != null){
                //添加到购物车的是菜品
                queryWrapper.eq(ShoppingCart::getDishId,dishId);
            }else{
                //添加到购物车的是套餐
                queryWrapper.eq(ShoppingCart::getSetmealId,shoppingCart.getSetmealId());
            }
    
            ShoppingCart cart = shoppingCartService.getOne(queryWrapper);
    
            //如果已存在,在原来数量基础上+1
            if(cart != null){
                Integer number = cart.getNumber();
                cart.setNumber(number+1);
                shoppingCartService.updateById(cart);
    
            }else{
                //如果不存在,则添加到购物车,数量默认就是1
                shoppingCart.setNumber(1);
                shoppingCart.setCreateTime(LocalDateTime.now());
                shoppingCartService.save(shoppingCart);
                cart = shoppingCart;
            }
    
            return R.success(cart);
        }
    }
  • 查询购物车中的菜品和套餐

    java 复制代码
    /**
         * 查看购物车当前数据
         * @return
         */
        @GetMapping("list")
        public R<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 R.success(list);
        }
  • 清空购物车操作

    java 复制代码
    /**
         * 清空购物车
         * @return
         */
        @DeleteMapping("clean")
        public R<String> clean(){
            LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());
    
            shoppingCartService.remove(queryWrapper);
    
            return R.success("清空购物车成功!");
        }

4. 下单

4.1 需求分析

  • 移动端用户将菜品或者套餐加入购物车后,可以点击购物车中的去结算按钮,页面跳转到订单确认页面,点击去支付按钮则完成下单操作。

4.2 数据模型

  • orders:订单表

    order_ detail::订单明细表

4.3 代码开发

  • 前端页面与服务端交互过程

    1、在购物车中点击去结算按钮,页面跳转到订单确认页面

    2、在订单确认页面,发送ajax请求,请求服务端获取当前登录用户的默认地址

    3、在订单确认页面,发送ajax请求,请求服务端获取当前登录用户的购物车数据

    4、在订单确认页面点击去支付按钮, 发送ajax请求, 请求服务端完成下单操作

  • 基本的类和接口

    实体类Orders、OrderDetail (直接从课程资料中导入即可)

    Mapper接口OrderMapper、OrderDetailMapper

    业务层接口OrderService、OrderDetailService

    业务层实现类OrderServicelmpl、OrderDetailServicelmpl

    控制层OrderController、OrderDetailController

  • OrderController代码:

    java 复制代码
    @RestController
    @RequestMapping("order")
    @Slf4j
    public class OrderController {
    
        @Autowired
        private OrdersService ordersService;
    
        /**
         * 用户下单
         * @param orders
         * @return
         */
        @PostMapping("submit")
        public R<String> submit(@RequestBody Orders orders){
            log.info("订单数据:{}",orders);
            ordersService.submit(orders);
            return R.success("下单成功");
        }
    }
  • OrdersServiceImpl代码:

    java 复制代码
    @Service
    public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders>
            implements OrdersService{
    
        @Autowired
        private ShoppingCartService shoppingCartService;
    
        @Autowired
        private UserService userService;
    
        @Autowired
        private AddressBookService addressBookService;
    
        @Autowired
        private OrderDetailService orderDetailService;
    
        /**
         * 用户下单
         * @param orders
         */
        @Override
        @Transactional
        public void submit(Orders orders) {
            //获取当前用户id
            Long currentId = BaseContext.getCurrentId();
    
            //查询当前用户购物车数据
            LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ShoppingCart::getUserId,currentId);
            List<ShoppingCart> shoppingCarts = shoppingCartService.list(queryWrapper);
    
            if(shoppingCarts == null || shoppingCarts.size() == 0){
                throw new CustomerException("购物车为空,不能下单");
            }
    
            //查询用户数据
            User user = userService.getById(currentId);
    
            //查询地址数据
            Long addressBookId = orders.getAddressBookId();
            AddressBook addressBook = addressBookService.getById(addressBookId);
            if(addressBook == null){
                throw new CustomerException("用户地址信息有误,不能下单");
            }
    
            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表插入数据,一条数据
            orders.setId(orderId);
            orders.setOrderTime(LocalDateTime.now());
            orders.setCheckoutTime(LocalDateTime.now());
            orders.setStatus(2);
            orders.setAmount(new BigDecimal(amount.get()));//总金额
            orders.setUserId(currentId);
            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);
    
            //向order_detail表插入数据,多条数据
            orderDetailService.saveBatch(orderDetails);
    
            //清空购物车数据
            shoppingCartService.remove(queryWrapper);
        }
    }
相关推荐
汤米粥1 分钟前
小皮PHP连接数据库提示could not find driver
开发语言·php
冰淇淋烤布蕾4 分钟前
EasyExcel使用
java·开发语言·excel
行然梦实7 分钟前
学习日记_20241110_聚类方法(K-Means)
学习·kmeans·聚类
拾荒的小海螺10 分钟前
JAVA:探索 EasyExcel 的技术指南
java·开发语言
马船长13 分钟前
制作图片木马
学习
秀儿还能再秀24 分钟前
机器学习——简单线性回归、逻辑回归
笔记·python·学习·机器学习
Jakarta EE27 分钟前
正确使用primefaces的process和update
java·primefaces·jakarta ee
WCF向光而行29 分钟前
Getting accurate time estimates from your tea(从您的团队获得准确的时间估计)
笔记·学习
马剑威(威哥爱编程)35 分钟前
哇喔!20种单例模式的实现与变异总结
java·开发语言·单例模式
白-胖-子1 小时前
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-统计数字
开发语言·c++·算法·蓝桥杯·等考·13级