菜品展示、购物车、下单
目录
2.3菜品展示---代码开发---修改DishController的list方法并测试 93
2.4菜品展示---代码开发---创建SetmealController的list方法并测试 94
3.6购物车---代码开发---查看购物车&清空购物车 97
4.3用户下单---代码开发---梳理交互过程&准备工作 99
4.6用户下单---代码开发(在OrderServiceImpl驱动类实现层实现submit方法实现)101
4.7用户下的那---代码开发(向订单表中进行数据的单条插入,订单明细多条数据插入,清空购物车数据)102
一、导入用户地址簿相关功能代码 90
1.1需求分析 90
1.2数据模型 90
1.3导入功能代码 90
二、菜品展示 91
2.1需求分析 91
2.2商品展示---代码开发---梳理交互过程 92
两个需求分析:
在客户端请求数据的展示:
前端部分的功能展示:和上面的两次list对应的关系
前端设置的是,这两部分同时正确的前提下,才能够在前端页面渲染成功。
目前的情况是:请求购物车的加载失败,所以这条渲染才没能够成功。
修改购物车请求的内容:
进行修改后:如果界面没有显示,可以使用ctrl+f5,进行刷新浏览器的缓存
2.3菜品展示---代码开发---修改DishController的list方法并测试 93
本部分功能主要实现的是,在移动端的界面能够进行点击“选择规格”后,会弹出口味的信息
本部分代码的实现,采用的就是之前展示菜品还要展示菜品对应的名称,这种类型的代码形式。
本部分代码实现:
/**
* 根据条件查询对应的菜品数据
* @param dish
* @return
*/
@GetMapping("/list")
public R<List<DishDto>> list(Dish dish){//这个部分传递的参数,可以是Long categoryid,
// 但是可以将其进行扩展使用,使用Dish类中的参数,它包含了很多的参数信息,包含categoryid
//构造查询条件
LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(dish.getCategoryId() != null , Dish::getCategoryId,dish.getCategoryId());
//该部分是设置一个判断语句,确定id传递过来,并不是空的指针
//添加排序条件
queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
//使用了两个判断条件,一个是根据sort进行升序排序,如果sort排序一致,再根据更新时间进行降序判断
//添加条件,查询状态为1(起售状态)的菜品
queryWrapper.eq(Dish::getStatus,1);
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();
//实现SQL语句:select * from dish_flavor where dish_id = ?
LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(DishFlavor::getDishId,dishId);
List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);
dishDto.setFlavors(dishFlavorList);//将上面查询得到的结果设置到dishDto中
return dishDto;//将处理后的数据结果返回出去
}).collect(Collectors.toList());
return R.success(dishDtoList);
}
2.4菜品展示---代码开发---创建SetmealController的list方法并测试 94
本部分需要解决的问题:套餐点击后出现接口异常。
对应的请求路径信息如下所示:但是之前程序代码编写的过程中并没有该该部分,所以需要进行编写该部分的代码。需要在setmealController中创建list方法。
本部分实际上就是通过IDEA编写代码,能够从数据库内根据自己需要的条件信息,来判断,获取得到对应的数据信息,进行反馈给移动端。
本部分实现的效果:
本部分的代码:在setmealController中添加list方法
/**
*根据条件查询套餐数据
* @param setmeal
* @return
*/
@GetMapping("/list")
public R<List<Setmeal>> list(Setmeal setmeal){
//SQL 筛选判断,两个等值判断+一个根据更新时间顺序进行降序排列
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);
}
三、购物车 95
3.1需求分析 95
将菜品或者菜品套餐添加到购物车,都是使用的同一个模型
注:一共有三个需求进行填写
3.2数据模型 95
3.3代码开发---梳理交互过程 95
3.4代码开发---准备工作 95
3.5购物车---代码开发---添加购物车 96
效果实现:实现商品添加购物车添加成功的功能
发送请求时,会有如下的操作指示:
实现效果:
1、菜品能够直接添加,并且能够在购物车内进行数量的增加
2、套餐的添加
本部分代码如下所示:
/**
* 添加购物车
* @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<>();
queryWrapper.eq(ShoppingCart::getUserId,currentId);
if(dishId != null){
//添加到购物车的是菜品
queryWrapper.eq(ShoppingCart::getDishId,dishId);
}else{
//添加到购物车的是套餐
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);
shoppingCart.setCreateTime(LocalDateTime.now());
shoppingCartService.save(shoppingCart);
cartServiceOne = shoppingCart;
}
return R.success(cartServiceOne);
}
3.6购物车---代码开发---查看购物车&清空购物车 97
不同的用户,拥有相互隔离的数据信息,之间不会进行干扰。
本部分实现的效果:在购物车进行查看,添加数量,并且能够看到对应的钱数发生改变。
本部分代码:
/**
* 查看购物车
* @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);
}
本部分实现在购物车部分对菜品的数量进行删减。
本部分的代码如下所示:
/**
* 清空购物车
* @return
*/
@DeleteMapping("/clean")
public R<String> clean(){
//SQL: delete from shopping_cart where user_id = ?
LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());
shoppingCartService.remove(queryWrapper);
return R.success("清空购物车成功");
}
四、用户下单 98
4.1需求分析 98
实现用户的结账支付。
4.2数据模型 98
4.3用户下单---代码开发---梳理交互过程&准备工作 99
移动端处理后的点击“去支付” 功能后发送的请求信息内容。
4.4用户下单---准备工作 99
4.5用户下单---代码开发 100
点击“去支付”之后,请求相应的内容如下所示:
如果数据处理过程中,处理的比较复杂,可以在驱动实现的Service服务层进行数据的方法的创建,随后再对应的驱动实现类进行使用。最终在对应的Controller层进行调用使用。
本部分主要
步骤一:实现简单在OrderController层方法搭建submit提交的框架:并调用后面两个步骤的内容的调用。
@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private OrderService orderService;
/**
* 用户下单
* @param orders
* @return
*/
@PostMapping("/submit")
public R<String> submit(@RequestBody Orders orders){
log.info("订单数据:{}",orders);
orderService.submit(orders);
return R.success("下单成功");
}
}
步骤二:
由于操作复杂在service层的接口层进行创建一个新的submit方法
public interface OrderService extends IService<Orders> {
/**
* 用户下单
* @param orders
*/
public void submit(Orders orders);
}
步骤三:在OrderServiceImpl驱动类实现层进行方法的编写。
4.6用户下单---代码开发(在OrderServiceImpl驱动类实现层实现submit方法实现)101
注本部分是要实现对多个表进行操作处理,需要使用处理多个数据库,即启动AOP事务的运行,所以使用注解@Transactional
实现前面的内容,只有下面的这些内容没有实现
4.7用户下的那---代码开发(向订单表中进行数据的单条插入,订单明细多条数据插入,清空购物车数据)102
1、订单表中数据单条插入
向表中插入数据则需要插入所插入表中的所有数据内容属性,进行编辑设置。
所有在请求中没有反馈的数据,需要在程序代码中进行插入设置。
代码实现:
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService {
@Autowired
private ShoppingCartService shoppingCartService;
@Autowired
private UserService userService;
@Autowired
private AddressBookService addressBookService;
@Autowired
private OrderDetailService orderDetailService;
/**
* 用户下单
* @param orders
*/
@Transactional
public void submit(Orders orders) {
//获得当前用户id
Long userId = BaseContext.getCurrentId();
//查询当前用户的购物车数据
LambdaQueryWrapper<ShoppingCart> wrapper = new LambdaQueryWrapper<>();//SQL:查询内容
wrapper.eq(ShoppingCart::getUserId,userId);
List<ShoppingCart> shoppingCarts = shoppingCartService.list(wrapper);
if(shoppingCarts == null || shoppingCarts.size() == 0){//进行异常的报错,当购物车的中没有物品时
throw new CustomException("购物车为空,不能下单");
}
//查询用户数据
User user = userService.getById(userId);
//查询地址数据
Long addressBookId = orders.getAddressBookId();
AddressBook addressBook = addressBookService.getById(addressBookId);
if(addressBook == null){
throw new CustomException("用户地址信息有误,不能下单");
}
long orderId = IdWorker.getId();//订单号
AtomicInteger amount = new AtomicInteger(0); //使用amount来作为购物车计算金额的计算,进行累加的处理
// 使用原子类型的,保证高并发、多线程时候使用的安全
//该部分是实现多条数据保存的操作处理,设置为集合List
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类中的属性数据信息进行填充,例如:id、number等等
orders.setId(orderId);
orders.setOrderTime(LocalDateTime.now());
orders.setCheckoutTime(LocalDateTime.now());
orders.setStatus(2);
orders.setAmount(new BigDecimal(amount.get()));//总金额
orders.setUserId(userId);
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(wrapper);
}
}