【瑞吉外卖 | 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);
        }
    }
相关推荐
极客先躯6 分钟前
高级java每日一道面试题-2024年11月22日-JVM篇-说说堆和栈的区别?
java·jvm··
2401_8574396934 分钟前
企业OA管理系统:Spring Boot技术应用与优化
java·spring boot·后端
2401_8574396935 分钟前
Spring Boot OA:构建企业级办公自动化平台
java·spring boot·后端
虾球xz40 分钟前
游戏引擎学习第21天
学习·游戏引擎
明月*清风1 小时前
【数据结构专栏】二叉搜索树(Binary Search Tree)的剖析?
开发语言·数据结构·c++·visualstudio
AI完全体1 小时前
【AI战略思考12】调整战略目标,聚焦数据分析,学习德川家康,剩者为王
人工智能·学习·数据分析·数据科学·找工作
paterWang1 小时前
小程序-基于java+SpringBoot+Vue的农场管理系统设计与实现
java·spring boot·小程序
尘浮生1 小时前
Java项目实战II基于Java+Spring Boot+MySQL的共享汽车管理系统(源码+数据库+文档)
java·数据库·spring boot·mysql·微信小程序·小程序·汽车
雪碧聊技术1 小时前
RabbitMQ3:Java客户端快速入门
java·开发语言·rabbitmq·amqp·spring amqp·rabbittemplate
Sinsa_SI1 小时前
2024年9月中国电子学会青少年软件编程(Python)等级考试试卷(六级)答案 + 解析
开发语言·python·等级考试·电子学会·考级