黑马-瑞吉外卖 day6 移动端开发

目录

1. 配送地址

1.1 新增地址

1.2 查询当前用户的全部地址

1.3 设置默认地址

2. 菜品展示

2.1 根据菜品分类展示菜品

2.2 根据套餐分类展示套餐

3. 购物车

3.1 查看购物车

3.2 添加餐品到购物车

3.3 清空购物车

4. 下单

4.1 查询默认地址

4.2 下单


1. 配送地址

1.1 新增地址

需要获取当前登录用户id,将该id与地址信息一起存进地址表中。

    /**
     * 新增地址
     * @param addressBook
     * @return
     */
    @PostMapping
    public R<String> save(@RequestBody AddressBook addressBook){
        log.info("address:"+addressBook);
        Long currentId = BaseContext.getCurrentId();
        addressBook.setUserId(currentId);
        addressBookService.save(addressBook);
        return R.success("新增成功");
    }

1.2 查询当前用户的全部地址

    /**
     * 根据用户id查询地址
     * @return
     */
    @GetMapping("/list")
    public R<List<AddressBook>> list (){
        //获取当前登录用户id
        Long currentId = BaseContext.getCurrentId();
        //查询该id下保存的所有地址信息
        LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AddressBook::getUserId,currentId);
        List<AddressBook> list = addressBookService.list(queryWrapper);
        //返回给前端
        return R.success(list);
    }

1.3 设置默认地址

    /**
     * 设置默认地址
     * @param addressBook
     * @return
     */
    @PutMapping("/default")
    public R<AddressBook> setDefault(@RequestBody AddressBook addressBook){
        //将当前用户的全部地址的idDefault字段更新为0,即全部设为非默认地址
        LambdaUpdateWrapper<AddressBook> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(AddressBook::getUserId,BaseContext.getCurrentId());
        updateWrapper.set(AddressBook::getIsDefault,0);
        addressBookService.update(updateWrapper);
        //通过id查询出该条地址,将其设为默认地址
        addressBook.setIsDefault(1);
        addressBookService.updateById(addressBook);
        return R.success(addressBook);
    }

2. 菜品展示

2.1 根据菜品分类展示菜品

修改DishController的list方法,因为需要返回菜品口味数据,所以需要将返回类型改为DishDto类型。

    /**
     * 根据分类id查询菜品
     * @param dish
     * @return
     */
    @GetMapping("/list")
    public R<List<DishDto>> getDishesByCategoryId(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> dishes = dishService.list(queryWrapper);
        List<DishDto> dishDtos = dishes.stream().map((item)->{
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(item,dishDto);

            LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(DishFlavor::getDishId,item.getId());
            List<DishFlavor> dishFlavors = dishFlavorService.list(lambdaQueryWrapper);
            dishDto.setFlavors(dishFlavors);

            return dishDto;
        }).collect(Collectors.toList());

        return R.success(dishDtos);
    }

2.2 根据套餐分类展示套餐

    /**
     * 根据条件查询套餐信息
     * @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());

        List<Setmeal> list = setmealService.list(queryWrapper);

        return R.success(list);
    }

3. 购物车

3.1 查看购物车

    /**
     * 查看购物车
     * @return
     */
    @GetMapping("/list")
    public R<List<ShoppingCart>> list(){
        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShoppingCart::getUserId, BaseContext.getCurrentId());
        List<ShoppingCart> list = shoppingCartService.list(queryWrapper);

        return R.success(list);

    }

3.2 添加餐品到购物车

系统设计Bug:购物车中只含有createTime字段,而不含有updateTime等字段,所以公共数据自动填充无法正常执行,在该字段上添加 @TableField(fill = FieldFill.INSERT_UPDATE) 注解会报错,而不添加会导致该字段为空。

解决办法:加上 @TableField(fill = FieldFill.INSERT_UPDATE) 注解的同时,修改元数据对象处理器类(MyMetaObjectHandler.java)中的自动填充方法,在填充之前判断一下该字段是否存在,存在才填充:

    /**
     * 插入操作自动填充
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("公共字段自动填充[insert]"+metaObject.toString());
        if (metaObject.hasSetter("createTime")){
            metaObject.setValue("createTime",LocalDateTime.now());
        }

        if (metaObject.hasSetter("updateTime")){
            metaObject.setValue("updateTime",LocalDateTime.now());
        }

        if (metaObject.hasSetter("createUser")){
            metaObject.setValue("createUser",BaseContext.getCurrentId());
        }

        if (metaObject.hasSetter("updateUser")){
            metaObject.setValue("updateUser",BaseContext.getCurrentId());
        }
    }

修改好之后可以正常实现添加餐品的业务逻辑了: 

    /**
     * 添加餐品到购物车
     * @param shoppingCart
     * @return
     */
    @PostMapping("/add")
    public R<ShoppingCart> add(@RequestBody ShoppingCart shoppingCart){

        //设置用户id
        shoppingCart.setUserId(BaseContext.getCurrentId());
        //查询当前菜品或套餐是否在购物车中
        Long dishId = shoppingCart.getDishId();
        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());
        if (dishId!=null){
            //添加的是菜品则根据菜品id查询
            queryWrapper.eq(ShoppingCart::getDishId,dishId);
        }else {
            //添加的是套餐则根据套餐id查询
            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);
            shoppingCartService.save(shoppingCart);
            cartServiceOne = shoppingCart;
        }
        //数据返回给前端
        return R.success(cartServiceOne);
    }

注:修改好的或者新增的一条购物车信息要返回给前端,特别要注意number字段是否有值,否则会出现点餐页面点击加号按钮餐品数量无法正常增加的情况。 

3.3 清空购物车

    /**
     * 清空购物车
     * @return
     */
    @DeleteMapping("/clean")
    public R<String> delete(){
        //根据用户id清空购物车
        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());
        shoppingCartService.remove(queryWrapper);

        return R.success("清空成功!");
    }

4. 下单

4.1 查询默认地址

    @GetMapping("/default")
    public R<AddressBook> getDefault(){
        //根据用户id查询默认地址
        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);
        }
    }

4.2 下单

注:

1. 计算总价时使用 AtomicInteger 类型的数据对象,线程安全,保证在多线程高并发的情况下不会计算出错;使用 BigDecimal 精度更高。

AtomicInteger amount = new AtomicInteger(0);
amount.addAndGet(item.getAmount().multiply(new BigDecimal(item.getNumber())).intValue());
orders.setAmount(new BigDecimal(amount.get()));

 2. 使用 IdWorker 生成订单id

long number = IdWorker.getId();
    /**
     * 下单
     * @param orders
     * @return
     */
    @Transactional
    @PostMapping("/submit")
    public R<String> submit(@RequestBody Orders orders){
        //获取当前用户id
        Long userId = BaseContext.getCurrentId();

        //查询当前用户的购物车数据
        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShoppingCart::getUserId,userId);
        List<ShoppingCart> shoppingCarts = shoppingCartService.list(queryWrapper);
        //如果购物车为空,抛出一个业务异常
        if(shoppingCarts == null || shoppingCarts.size() == 0){
            throw new CustomException("购物车为空,不能下单");
        }

        //查询当前用户信息
        User user = userService.getById(userId);

        //查询地址信息
        LambdaQueryWrapper<AddressBook> queryWrapper2 = new LambdaQueryWrapper<>();
        queryWrapper2.eq(AddressBook::getId,orders.getAddressBookId());
        AddressBook addressBook = addressBookService.getOne(queryWrapper2);

        //生成订单号
        long number = IdWorker.getId();

        //创建AtomicInteger类型的数据对象,线程安全,保证在多线程高并发的情况下不会计算出错
        AtomicInteger amount = new AtomicInteger(0);

        //遍历购物车数据,设置订单详细信息
        List<OrderDetail> orderDetails = shoppingCarts.stream().map((item)->{

            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(number); //设置订单号
            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()); //设置单价

            //计算订单总价,使用 BigDecimal 精度更高
            amount.addAndGet(item.getAmount().multiply(new BigDecimal(item.getNumber())).intValue());
            return orderDetail;

        }).collect(Collectors.toList());
        //向订单表插入数据,一条

        orders.setId(number);
        orders.setNumber(String.valueOf(number)); //设置订单号
        orders.setOrderTime(LocalDateTime.now()); //设置下单时间
        orders.setCheckoutTime(LocalDateTime.now()); //设置支付时间
        orders.setUserId(userId); //设置下单用户id
        orders.setUserName(user.getName()); //设置下单人姓名
        orders.setAddress(addressBook.getDetail()); //设置地址
        orders.setConsignee(addressBook.getConsignee()); //设置地址联系人姓名
        orders.setPhone(addressBook.getPhone()); //设置地址联系人电话
        orders.setAmount(new BigDecimal(amount.get())); //设置总价

        orderService.save(orders);
        //向订单明细表插入数据,多条
        orderDetailService.saveBatch(orderDetails);
        //清空购物车数据
        shoppingCartService.remove(querywrapper);

        return R.success("下单成功");
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值