一、短信发送
短信服务介绍
目前市面上有很多第三方提供的短信服务,这些第三方短信服务会和各个运营商(移动、联通、电信)对接,只需要注册成为会员并且按照提供的开发文档进行调用就可以发送短信。
阿里云短信服务介绍
短信服务(Short Message Service)是广大企业客户快速触达手机用户所优选使用的通信能力。调用API或用群发助手,即可发送验证码、通知类和营销类短信;国内验证短信秒级触达,到达率最高可达99%;国际/港澳台短信覆盖200多个国家和地区,安全稳定,广受出海企业选用。
代码开发
使用阿里云短信服务发送短信,可以参照官方提供的文档即可。
具体开发步骤:1.导入maven坐标;2.调用API
Maven坐标:
二、手机验证码登录
需求分析
为了方便用户登录,移动端通常都会提供通过手机验证码登录的功能。
注意:通过手机验证码登录,手机号是区分不同用户的标识。
数据模型
通过手机验证码登录时,涉及的表为user表,即用户表。
代码开发
登录时前端页面和服务端的交互过程:
1.登录页面(front/page/login.html)输入手机号,点击【获取验证码】按钮,页面发送ajax请求,在服务端调用短信服务API给指定手机号发送验证码短信;
2.在登录页面输入验证码,点击【登录】按钮,发送ajax请求,在服务端处理登录请求。
开发手机验证码登录功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求。
需要用到的类和接口:
实体类User、Mapper接口UserMapper、业务层接口UserService、业务层实现类UserServiceImpl、控制层UserController、工具类SMSUtils、ValidateCodeUtils。
修改LoginCheckFilter
前面我们也就完成了LoginCheckFilter过滤器的开发,此过滤器用于检测用户的登录状态。在进行手机验证码登录时,发送的请求需要在此过滤器处理时直接放行。
在LoginCheckFilter过滤器中扩展逻辑,判断移动端用户登录状态:
发送验证码
这里没有使用阿里云发送短信验证码,而是控制台输出验证码,登录时输入
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
@Autowired
private UserService userService;
/**
* 发送手机短信验证码
* @param user
* @param session
* @return
*/
@PostMapping("/sendMsg")
public R<String> sendMsg(@RequestBody User user, HttpSession session){
//获取手机号
String phone = user.getPhone();
//判断手机号是否为空
if(StringUtils.isNotEmpty(phone)){
//生成随机4位验证码
String code = ValidateCodeUtils.generateValidateCode(4).toString();
log.info("code={}",code);
//调用阿里云提供的短信服务API完成发送短信
//SMSUtils.sendMessage("瑞吉外卖","",phone,code);
//需要将生成的验证码保存到session中
session.setAttribute(phone,code);
return R.success("短信验证码发送成功");
}
return R.error("短信验证码发送失败");
}
登录时输入手机号和验证码,前端页面发送的请求
携带的参数
/**
* 移动端登录
* @param map
* @param session
* @return
*/
@PostMapping("/login")
public R<User> login(@RequestBody Map map, HttpSession session){//User实体类中没有code属性,所以不能用user接收,这里可以使用map键值对接收,或者Dto类型接收
log.info(map.toString());
//获取手机号
String phone = map.get("phone").toString();
//获取验证码
String code = map.get("code").toString();
//从Session中获取保存的验证码
Object codeInSession = session.getAttribute(phone);
//进行验证码的比对(页面提交的验证码和session中的验证码对比)
if(codeInSession != null && codeInSession.equals(code)){
//对比成功,则登录
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getPhone,phone);
User user = userService.getOne(queryWrapper);
//判断当前登录用户是否为新用户,如果是则自动完成注册
if(user == null){
user = new User();
user.setPhone(phone);
user.setStatus(1);
userService.save(user);
}
session.setAttribute("user",user.getId());//登录成功后要把用户的id在session中存一份,因为经过过滤器后要校验
return R.success(user);
}
return R.error("登录失败");
}
登录后的界面
三、导入用户地址簿
需求分析
地址簿,指的是移动端消费者用户的地址信息,用户登录成功后可以维护自己的地址信息。同一个用户可以有多个地址信息,但是只有一个默认地址。
数据模型
用户的地址信息会存储在address_book表,即地址薄表中。
代码开发
需要用到的类和接口:
实体类AddressBook、Mapper接口AddressBookMapper、业务层接口AddressBookService、业务层实现类AddressBookServiceImpl、控制层AddressBookController
新增地址:
/**
* 新增地址
*/
@PostMapping
public R<AddressBook> save(@RequestBody AddressBook addressBook) {
addressBook.setUserId(BaseContext.getCurrentId());
log.info("addressBook:{}", addressBook);
addressBookService.save(addressBook);
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));
}
根据id查询地址:
/**
* 根据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("没有找到该对象");
}
}
设置默认地址:
/**
* 设置默认地址
*/
@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); //将所有地址的默认值都设为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);
}
查询默认地址:
/**
* 查询默认地址
*/
@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);
}
}
修改地址:
修改地址时,首先要进行数据回显,即根据id查询地址(已经写好)
修改完之后,点击保存,前端发出的请求:
携带参数
/**
* 修改地址
* @param addressBook
* @return
*/
@PutMapping
public R<AddressBook> update(@RequestBody AddressBook addressBook){
if(addressBook == null){
return R.error("出现错误");
}else {
addressBookService.updateById(addressBook);
return R.success(addressBook);
}
}
删除地址:
/**
* 删除地址
* @param ids
* @return
*/
@DeleteMapping
public R<String> delete(@RequestParam Long ids){
if(ids == null){
return R.error("出现错误");
}else {
LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(AddressBook::getUserId,BaseContext.getCurrentId()).eq(AddressBook::getId,ids);
addressBookService.remove(queryWrapper);
return R.success("删除地址成功");
}
}
四、菜品展示
需求分析
用户登录成功后跳转到系统首页,在首页需要根据分类来展示菜品和套餐。如果菜品设置了口味信息,需要展示【选择规格】按钮,否则显示【+】按钮。
代码开发
前端页面和服务端的交互过程:
1.页面(front/index.html)发送ajax请求,获取分类数据(菜品分类和套餐分类);
2.页面发送ajax请求,获取一个分类下的菜品或者套餐。
开发菜品展示功能,其实就是在服务端编写代码去处理前端页面发送的2次请求即可。
注意:首页完成加载后,还发送了一次ajax请求用于加载购物车数据,此处可以将这次请求的地址暂时修改以下,从静态json文件获取数据,等后续开发购物车功能时再修改回来。
获取分类数据(之前写过),发送请求
获取一个分类下的菜品(之前写过),发送请求
DishController中获得菜品分类下的数据,没有口味数据
没有口味数据,页面显示
修改菜品分类下菜品数据,并增加口味数据
/**
* 新增菜品中,根据条件查询菜品分类下对应的菜品数据,增加菜品口味数据
* @param dish
* @return
*/
@GetMapping("/list")
public R<List<DishDto>> list(Dish dish){
LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
//查询条件
queryWrapper.eq(dish.getCategoryId() != null,Dish::getCategoryId,dish.getCategoryId());
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);
LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(DishFlavor::getDishId,item.getId());
List<DishFlavor> flavors = dishFlavorService.list(lambdaQueryWrapper);
dishDto.setFlavors(flavors);
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,1);
queryWrapper.orderByDesc(Setmeal::getUpdateTime);
List<Setmeal> list = setmealService.list(queryWrapper);
return R.success(list);
}
页面显示(未展示套餐下菜品信息)
五、购物车
需求分析
移动端用户可以将菜品或者套餐添加到购物车。对于菜品来说,如果设置了口味信息,则需要选择规格后才能加入购物车;对于套餐来说,可以直接点击【+】将当前套餐加入购物车。在购物车中可以修改菜品和套餐的数量,也可以清空购物车。
数据模型
购物车对应的数据表为shopping_cart表
代码开发
添加菜品/套餐到购物车
前端页面和服务端的交互过程:
1.点击【加入购物车】或者【+】按钮,页面发送ajax请求,请求服务端,将菜品或者套餐添加到购物车;
2.点击购物车图标,页面发送ajax请求,请求服务端查询购物车中的菜品和套餐;
3.点击清空购物车按钮,页面发送ajax请求,请求服务端来执行清空购物车操作。
开发购物车功能,其实就是在服务端编写代码去处理前端页面发送的这3次请求即可。
需要用到的类和接口:
实体类ShoppingCart、Mapper接口ShoppingCartMapper、业务层接口ShoppingCartService、业务层接口实现类ShoppingCartServiceImpl、控制层ShoppingCartController
@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);
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 shoppingcart where user_id = ? and dish_id/setmeal_id = ?
ShoppingCart cartServiceOne = shoppingCartService.getOne(queryWrapper);
//如果已经存在,就在原来数量基础上加1
if(cartServiceOne != null){
Integer number = cartServiceOne.getNumber();
cartServiceOne.setNumber(number + 1);
shoppingCartService.updateById(cartServiceOne);
}else {
//如果不存在,则添加到购物车上,数量默认就是1
shoppingCart.setNumber(1);
shoppingCartService.save(shoppingCart);
cartServiceOne = shoppingCart;
}
return R.success(cartServiceOne);
}
}
查看购物车订单
前端发送的请求
/**
* 查看购物车订单
* @return
*/
@GetMapping("/list")
public R<List<ShoppingCart>> list(){
Long currentId = BaseContext.getCurrentId();
LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ShoppingCart::getUserId,currentId);
queryWrapper.orderByDesc(ShoppingCart::getCreateTime);
List<ShoppingCart> list = shoppingCartService.list(queryWrapper);
return R.success(list);
}
清空购物车
前端发送的请求
/**
* 清空购物车
* @return
*/
@DeleteMapping("/clean")
public R<String> clean(){
LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());
shoppingCartService.remove(queryWrapper);
return R.success("清空购物车成功");
}
减少购物车菜品或者套餐订单
/**
* 减少购物车中菜品或者套餐
* @param shoppingCart
* @return
*/
@PostMapping("/sub")
public R<ShoppingCart> sub(@RequestBody ShoppingCart shoppingCart){
Long dishId = shoppingCart.getDishId();
LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());
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);
if(cartServiceOne.getNumber() == 0){
shoppingCartService.remove(queryWrapper);
}else{
shoppingCartService.updateById(cartServiceOne);
}
}
return R.success(cartServiceOne);
}
六、用户下单
需求分析
移动端用户将菜品或者套餐加入购物车后,可以点击购物车中的【去结算】按钮,页面跳转到订单确认页面,点击【去支付】按钮完成下单操作。
数据模型
用户下单业务对应的数据表为订单表orders和订单明细表order_detail
代码开发
前端页面和服务端的交互过程:
1.在购物车中点击【去结算】按钮,页面跳转到订单确认页面;
2.在订单确认页面,发送ajax请求,请求服务端获取当前登录用户的默认地址;
3.在订单确认页面,发送ajax请求,请求服务端获取当前登录用户的购物车数据;
4.在订单确认页面点击【去支付】按钮,发送ajax请求,请求服务端完成下单操作。
开发用户下单功能,其实就是在服务端编写代码去处理前端页面发送的请求即可。
所需的类和接口:
实体类:Orders、OrderDetai;Mapper接口:OrderMapper、OrderDetailMapper;业务层接口:OrderService、OrderDetailService;业务层接口实现类:OrderServiceImpl、OrderDetailServiceImpl;控制层:OrderController、OrderDetailController
点击去结算,前端页面发送的请求:
点击去支付,发送的请求:
携带参数
package com.huangzx.reggie.controller;
import com.huangzx.reggie.common.R;
import com.huangzx.reggie.pojo.Orders;
import com.huangzx.reggie.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping("/submit")
public R<String> submit(@RequestBody Orders orders){
log.info("订单数据:{}",orders);
orderService.sumbit(orders);
return R.success("下单成功");
}
}
OrderServiceImpl实现submit方法
package com.huangzx.reggie.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huangzx.reggie.common.BaseContext;
import com.huangzx.reggie.common.CustomException;
import com.huangzx.reggie.mapper.OrderMapper;
import com.huangzx.reggie.pojo.*;
import com.huangzx.reggie.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@Service
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;
@Transactional
public void sumbit(Orders orders) {
//获取当前用户的id
Long userId = BaseContext.getCurrentId();
//查询当前用户的购物车数据
LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ShoppingCart::getUserId,userId);
List<ShoppingCart> list = shoppingCartService.list(queryWrapper);
if(list == null || list.size() == 0){
throw new CustomException("购物车为空,不能下单");
}
//查询用户数据
User user = userService.getById(userId);
//查询地址数据
Long addressBookId = orders.getAddressBookId();//获取携带的参数中的地址id
AddressBook addressBook = addressBookService.getById(addressBookId);
if(addressBook == null){
throw new CustomException("用户地址信息有误,不能下单");
}
long orderId = IdWorker.getId(); //订单号
//订单明细表,计算金额和设置其他属性值
AtomicInteger amount = new AtomicInteger(0); //计算订单总金额 原子操作,保证线程安全
List<OrderDetail> orderDetails = list.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(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(queryWrapper);
}
}
点击查看订单,发送的请求
使用分页查询
从页面返回的数据结果,发现还需要订单的明细。所以需要完善代码
Orders表里没有订单明细属性,这里使用OrdersDto,封装订单明细属性
首先在OrderDetailServiceImpl实现根据订单id查看订单明细的方法
完善后的方法
/**
* 用户订单分页查询
* @param page
* @param pageSize
* @return
*/
@GetMapping("/userPage")
public R<Page> page(int page,int pageSize){
Page<Orders> pageInfo = new Page<>(page,pageSize);
Page<OrdersDto> ordersDtoPage = new Page<>();
LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Orders::getUserId, BaseContext.getCurrentId());
queryWrapper.orderByDesc(Orders::getOrderTime);
orderService.page(pageInfo,queryWrapper);
BeanUtils.copyProperties(pageInfo,ordersDtoPage,"records");
List<Orders> records = pageInfo.getRecords();
List<OrdersDto> list = records.stream().map((item) ->{
OrdersDto ordersDto = new OrdersDto();
BeanUtils.copyProperties(item,ordersDto);
Long id = item.getId();
List<OrderDetail> orderDetail = orderDetailService.getByOrderId(id);
if(orderDetail != null){
ordersDto.setOrderDetails(orderDetail);
}
return ordersDto;
}).collect(Collectors.toList());
ordersDtoPage.setRecords(list);
return R.success(ordersDtoPage);
}
再来一单方法
将订单的状态改为4(已完成) 订单状态 1待付款,2待派送,3已派送,4已完成,5已取消。会有再来一单的选项
前端发送的请求
/**
* 再来一单
* 先清除之前购物车的数据,再把再来一单中的菜品数据重新写入购物车中
* @param map
*/
@PostMapping("/again")
public R<String> againSubmit(@RequestBody Map<String,String> map){
String ids = map.get("id");
long id = Long.parseLong(ids);
LambdaQueryWrapper<OrderDetail> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(OrderDetail::getOrderId,id);
List<OrderDetail> orderDetailList = orderDetailService.list(queryWrapper);
LambdaQueryWrapper<ShoppingCart> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ShoppingCart::getId,id);
shoppingCartService.remove(wrapper);
Long currentId = BaseContext.getCurrentId();
List<ShoppingCart> shoppingCartList = orderDetailList.stream().map((item)->{
ShoppingCart shoppingCart = new ShoppingCart();
BeanUtils.copyProperties(item,shoppingCart);
shoppingCart.setUserId(currentId);
Long dishId = item.getDishId();
Long setmealId = item.getSetmealId();
String dishFlavor = item.getDishFlavor();
if(dishId != null){
shoppingCart.setDishId(dishId);
shoppingCart.setDishFlavor(dishFlavor);
}else {
shoppingCart.setSetmealId(setmealId);
}
shoppingCart.setName(item.getName());
shoppingCart.setNumber(item.getNumber());
shoppingCart.setAmount(item.getAmount());
shoppingCart.setImage(item.getImage());
shoppingCart.setCreateTime(LocalDateTime.now());
return shoppingCart;
}).collect(Collectors.toList());
shoppingCartService.saveBatch(shoppingCartList);
return R.success("再来一单成功");
}
查看套餐中菜品
点击套餐,当需要查看套餐中的菜品时,发出的请求:
/**
* 移动端点击套餐,查看菜品详情
* @param SetmealId
* @return
*/
@GetMapping("/dish/{SetmealId}")
public R<List<DishDto>> dishInfo(@PathVariable Long SetmealId){
LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SetmealDish::getSetmealId,SetmealId);
List<SetmealDish> list = setmealDishService.list(queryWrapper);
List<DishDto> dishDtoList = list.stream().map((item) ->{
DishDto dishDto = new DishDto();
BeanUtils.copyProperties(item,dishDto);
Long dishId = item.getDishId();
Dish dish = dishService.getById(dishId);
BeanUtils.copyProperties(dish,dishDto);
return dishDto;
}).collect(Collectors.toList());
return R.success(dishDtoList);
}
完成后效果
网页端查询订单明细
输入查询条件,发送的请求
携带的参数
采用上面书写的代码,可以发现没有用户的信息,因为userName为null,无法获取到值
完善代码。使用OrdersDto从orderDetail中获取下单人的值
/**
* 后台查看订单明细
* @param page
* @param pageSize
* @param number
* @param beginTime
* @param endTime
* @return
*/
@GetMapping("/page")
public R<Page> page(int page,int pageSize,String number,String beginTime,String endTime){
Page<Orders> pageInfo = new Page<>(page,pageSize);
Page<OrdersDto> ordersDtoPage = new Page<>();
LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(number != null,Orders::getNumber,number);
queryWrapper.gt(StringUtils.isNotEmpty(beginTime),Orders::getOrderTime,beginTime);
queryWrapper.lt(StringUtils.isNotEmpty(endTime),Orders::getOrderTime,endTime);
orderService.page(pageInfo,queryWrapper);
BeanUtils.copyProperties(pageInfo,ordersDtoPage,"records");
List<Orders> records = pageInfo.getRecords();
List<OrdersDto> list = records.stream().map((item) ->{
OrdersDto ordersDto = new OrdersDto();
BeanUtils.copyProperties(item,ordersDto);
String userName = item.getConsignee();
ordersDto.setUserName(userName);
return ordersDto;
}).collect(Collectors.toList());
ordersDtoPage.setRecords(list);
return R.success(ordersDtoPage);
}
修改订单状态
完成派送时,订单的状态为3,对于没有完成派送的订单,点击派送可以修改订单的状态
发送的请求:
携带参数
/**
* 修改订单状态
* @param map
* @return
*/
@PutMapping
public R<String> status(@RequestBody Map map){
String id = (String) map.get("id");
Long orderId = Long.parseLong(id);
Integer status = (Integer) map.get("status");
if(orderId == null || status == null){
return R.success("出现错误");
}
Orders orders = orderService.getById(orderId);
orders.setStatus(status);
orderService.updateById(orders);
return R.success("修改状态成功");
}
移动端退出功能
发送请求
/**
* 移动端退出功能
* @param request
* @return
*/
@PostMapping("/loginout")
public R<String> loginout(HttpServletRequest request){
request.getSession().removeAttribute("user");//清理session中id
return R.success("退出成功");
}