瑞吉外卖day7
菜品展示,购物车,下单
导入用户地址薄相关功能
需求分析
地址簿,指的是移动端消费者用户的地址信息,用户登录成功后可以维护自己的地址信息。同一个用户可以有多个地
址信息,但是只能有一个默认地址.
代码开发
@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)); }
菜品展示
需求分析
用户登录成功后跳转到系统首页,在首页需要根据分类来展示菜品和套餐。如果菜品设置了口味信息,需要展示
选择规格 按钮,否则显示+按钮。
代码开发-梳理交互过程
在开发代码之前,需要梳理一下前端页面和服务端的交互过程:1、页面(front/index.html)发送ajax请求,获取分类数据 (菜品分类和套餐分类)2、页面发送ajax请求,获取第一个分类下的菜品或者套餐开发菜品展示功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。
注意:首页加载完成后,还发送了一次aiax请求用于加载购物车数据,此处可以将这次请求的地址暂时修改一下,从静态ison文件获取数据,等后续开发购物车功能时再修改回来
代码开发
菜品展示存在bug,无法展示菜品口味,重写dishController中的list方法,获取到dishDto对象返回给客户端
@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 //根据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); //SQL:select * from dish_flavor where dish_id = ? List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper); dishDto.setFlavors(dishFlavorList); return dishDto; }).collect(Collectors.toList()); return R.success(dishDtoList); }
套餐页面无法正常展示,根据条件查询套餐
/** * 根据条件查询套餐数据 * @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); } }
购物车
需求分析
移动端用户可以将菜品或者套餐添加到购物车。对于菜品来说,如果设置了口味信息,则需要选择规格后才能加入购物车;对于套餐来说,可以直接点击 4加号将当前套餐加入购物车。在购物车中可以修改菜品和套餐的数量也可以清空购物车
代码开发-梳理交互过程
需要梳理一下购物车操作时前端页面和服务端的交互过程:
在开发代码之前,
1、点击加入购物车或者+ 按钮,页面发送ajax请求,请求服务端,将菜品或者套餐添加到购物车
2、点击购物车图标,页面发送ajax请求,请求服务端查询购物车中的菜品和套餐
3、点击清空购物车按钮,页面发送aiax请求,请求服务端来执行清空购物车操作
添加购物车
/** * 将菜品添加到购物车 * @param shoppingCart * @return */ @PostMapping("/add") public R<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<>(); if (dishId!=null){ //添加到购物车的是菜品 queryWrapper.eq(ShoppingCart::getDishId,dishId); }else { queryWrapper.eq(ShoppingCart::getSetmealId,shoppingCart.getSetmealId()); } 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(shoppingCart); }
查看购物车
/** * 查看购物车 * @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); }
清空购物车
@DeleteMapping("/clean") public R<String> clean(){ LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId()); shoppingCartService.remove(queryWrapper); return R.success("清空成功"); }
用户下单
需求分析
移动端用户将菜品或者套餐加入购物车后,可以点击购物车中去结算按钮,页面跳转到订单确认页面,点去支付按钮则完成下单操作。
代码开发-梳理交互过程
在开发代码之前,需要梳理一下用户下单操作时前端页面和服务端的交互过程
1、在购物车中点击按钮,页面跳转到订单确认页面去结算
2、在订单确认页面发送ajax请求,请求服务端获取当前登录用户的默认地址
3、在订单确认页面,发送ajax请求,请求服务端获取当前登录用户的购物车数据
4、在订单确认页面点击按钮,发送ajax请求,请求服务端完成下单操作去支付
开发用户下单功能,其实就是在服务端编写代码去处理前端页面发送的请求即可
代码开发
@PostMapping("/submit") public R<String> sunmit(@RequestBody Orders orders){ log.info("订单信息{}",orders); orderService.submit(orders); return R.success("下单成功"); }
/** * 提交订单 * @param orders */ @Override 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 CustomException("购物车为空,不能下单"); } //获取用户数据 User user = userService.getById(currentId); //获取地址数据 Long addressBookId = orders.getAddressBookId(); AddressBook addressBook = addressBookService.getById(addressBookId); if (addressBook==null){ throw new CustomException("地址为空,不能下单"); } //向订单表插入一条数据 long orderId = IdWorker.getId();//订单id 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(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); //向订单明细表插入数据,多条数据 orderDetailService.saveBatch(orderDetails); //清空购物车数据 shoppingCartService.remove(queryWrapper); }