瑞吉外卖业务开发(4)

简介: 瑞吉外卖业务开发

瑞吉外卖业务开发(3)https://developer.aliyun.com/article/1530407

新增套餐

需求分析

套餐就是菜品的集合。

后台系统中可以管理套餐信息,通过新增套餐功能来添加一个新的套餐,在添加套餐时需要选择当前套餐所属的套餐分类和包含的菜品,并且需要上传套餐对应的图片,在移动端会按照套餐分类来展示对应的套餐。

数据模型

新增套餐,其实就是将新增页面录入的套餐信息插入到setmeal表,还需要向setmeal_dish表插入套餐和菜品关联数据所以在新增套餐时,涉及到两个表:

  • setmeal 套餐表
  • setmeal_dish套餐菜品关系表

代码开发

准备工作

需要准备好的类和接口

  • 实体类SetmealDish,直接导入即可
  • DTO SetmealDto 直接导入即可
  • Mapper接口SetmealDishMapper
  • 业务层接口SetmealDishService
  • 业务层实现类SetmealDishServiceImpl
  • 控制层SetmealController

梳理交互过程

在开发代码之前,需要梳理一下新增套餐时前端页面和服务端的交互过程:

1、页面(backend/page/combo/add.html)发送ajax请求,请求服务端获取套餐分类数据并展示到下拉框中

2、页面发送ajax请求,请求服务端获取菜品分类数据并展示到添加菜品窗口中

3、页面发送ajax请求,请求服务端,根据菜品分类查询对应的菜品数据并展示到添加菜品窗口中

4、页面发送请求进行图片上传,请求服务端将图片保存到服务器

5、页面发送请求进行图片下载,将上传的图片进行回显

6、点击保存按钮,发送ajax请求,将套餐相关数据以json形式提交到服务端

开发新增套餐功能,其实就是在服务端编写代码去处理前端页面发送的这6次请求即可。

/**  
 * 根据条件查询对应的菜品数据  
 * @param dish  
 * @return  
 */  
@GetMapping("/list")  
public R<List<Dish>> 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);  
    return R.success(list);  
}
@Autowired  
private SetmealDishService setmealDishService;  
@Transactional  
@Override  
public void saveWithDish(SetmealDto setmealDto) {  
    //保存套餐的基本信息  
    this.save(setmealDto);  
    //保存套餐和菜品的关联信息  
    List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();  
setmealDishes.stream().map((item)->{  
        item.setSetmealId(setmealDto.getId());  
        return item;  
    }).collect(Collectors.toList());  
   setmealDishService.saveBatch(setmealDishes);  
  
  
}

controller

/**  
 * 新增套餐  
 * @param setmealDto  
 * @return  
 */  
@PostMapping  
public R<String> save(@RequestBody SetmealDto setmealDto){  
    setmealService.saveWithDish(setmealDto);  
    return R.success("新建套餐成功");  
}

套餐列表分页信息

在开发代码之前,需要梳理一下套餐分页查询时前端页面和服务端的交互过程:

1、页面(backend/page/combo/list.html)发送ajax请求,将分页查询参数(page.pageSize,name)提交到服务端,获取分页数据

2、页面发送请求,请求服务端进行图片下载,用于页面图片展示

开发套餐信息分页查询功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。

@GetMapping("/page")  
public R<Page> page(int page,int pageSize,String name){  
     Page<Setmeal> pageInfo = new Page<>();  
     Page<SetmealDto> setmealDtoPage=new Page<>();  
  
    LambdaQueryWrapper<Setmeal> queryWrapper=new LambdaQueryWrapper<>();  
    queryWrapper.like(name!=null,Setmeal::getName,name);  
    queryWrapper.orderByDesc(Setmeal::getUpdateTime);  
    setmealService.page(pageInfo,queryWrapper);  
    BeanUtils.copyProperties(pageInfo,setmealDtoPage,"records");  
    List<Setmeal> records = pageInfo.getRecords();  
  
  
   List<SetmealDto> list=  records.stream().map((item)->{  
        SetmealDto setmealDto = new SetmealDto();  
       BeanUtils.copyProperties(item,setmealDto);  
        Long categoryId = item.getCategoryId();  
        Category category = categoryService.getById(categoryId);  
       if(category!=null){  
           String name1 = category.getName();  
           setmealDto.setCategoryName(name1);  
  
       }  
       return setmealDto;  
    }).collect(Collectors.toList());  
   setmealDtoPage.setRecords(list);  
    return R.success(setmealDtoPage);

删除套餐

需求分析

删除套餐有批量删除和单个删除,我们可以用数组接收传过来的id,这样就可以使用一个来实现批量删除和单个删除的功能,还要注意的是,我们在删除套餐的时候还要删除与之对应的套餐,菜品关系表的相关信息,(我套餐都没了还要套餐菜品关系干啥)

手机验证码登录

阿里云短信服务-介绍

阿里云短信服务(Short Message Service)是广大企业客户快速触达手机用户所优选使用的通信能力。调用API或用群发助手,即可发送验证码、通知类和营销类短信;国内验证短信秒级触达,到达率最高可达99%;国际/港澳台短信覆盖200多个国家和地区,安全稳定,广受出海企业选用。

应用场景:

  • 验证码
  • 短信通知
  • 推广短信

步骤

  1. 导入maven坐标
  2. 调用api
<dependency>
<groupId>com.aliyun</ groupId>
<artifactId>aliyun-java-sdk-core< / artifactId><version>4.5.16</version>
< / dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi< / artifactId><version>2.1.0</version>
</ dependency>

需求分析

为了方便用户登录,移动端通常都会提供通过手机验证码登录的功能。

手机验证码登录的优点:

  • 方便快捷,无需注册,直接登录
  • 使用短信验证码作为登录凭证,无需记忆密码
  • 安全
    登录流程:
    输入手机号>获取验证码>输入验证码>点击登录>登录成功
    注意:通过手机验证码登录,手机号是区分不同用户的标识。

数据模型

代码开发

流程梳理

在开发代码之前,需要梳理一下登录时前端页面和服务端的交互过程:

1、在登录页面(front/page/login.html)输入手机号,点击【获取验证码】按钮,页面发送ajax请求,在服务端调用短信服务API给指定手机号发送验证码短信

2、在登录页面输入验证码,点击【登录】按钮,发送ajax请求,在服务端处理登录请求

开发手机验证码登录功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。

地址簿

需求分析

地址簿,指的是移动端消费者用户的地址信息,用户登录成功后可以维护自己的地址信息。同一个用户可以有多个地址信息,但是只能有一个默认地址。

数据模型

导入功能代码

功能代码清单

  • 实体类AddressBook(直接从课程资料中导入即可)
  • Mapper接口AddressBookMapper
  • 业务层接口AddressBookService
  • 业务层实现类AddressBookServicelmpl
  • 控制层AddressBookController (直接从课程资料中导入即可)

菜品展示

用户登录成功后跳转到系统首页,在首页需要根据分类来展示菜品和套餐。如果菜品设置了口味信息,需要展示

选择规格按钮,否则显示按钮。

代码开发

在开发代码之前,需要梳理一下前端页面和服务端的交互过程:

1、页面(front/index.html)发送ajax请求,获取分类数据(菜品分类和套餐分类)

2、页面发送ajax请求,获取第一个分类下的菜品或者套餐

开发菜品展示功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。

注意:首页加载完成后,还发送了一次ajax请求用于加载购物车数据,此处可以将这次请求的地址暂时修改一下,从静态json文件获取数据,等后续开发购物车功能时再修改回来,如下:

菜品展示的同时获得菜品的口味信息

@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();  
            //拷贝Dish里面的属性到DishDto  
            BeanUtils.copyProperties(item, dishDto);  
            //查询到分类id  
            Long categoryId = item.getCategoryId();  
            Category category = categoryService.getById(categoryId);  
            if (category != null) {  
                //通过分类id查询到分类名称  
                String categoryName = category.getName();  
                dishDto.setCategoryName(categoryName);  
            }  
  
            Long dishid = item.getId();//获取dishid  
            //获取口味表  
            LambdaQueryWrapper<DishFlavor> dishFlavorLambdaQueryWrapper = new LambdaQueryWrapper<>();  
            dishFlavorLambdaQueryWrapper.eq(DishFlavor::getDishId,dishid);  
  
            List<DishFlavor> dishFlavors = dishFlavorService.list(dishFlavorLambdaQueryWrapper);  
            dishDto.setFlavors(dishFlavors);  
  
            return dishDto;  
//最后通过collect收集成集合  
        }).collect(Collectors.toList());  
        return R.success(dishDtoList);  
    }

查询套餐信息

@GetMapping("/list")  
public R<List<Setmeal>> listR(@RequestBody 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);  
  
}

购物车

需求分析

移动端用户可以将菜品或者套餐添加到购物车。对于菜品来说,如果设置了口味信息

则需要选择规格后才能

加入购物车;对于套餐来说,可以直接点击将当前套餐加入购物车。在购物车中可以修改菜品和套餐的数量,也可以清空购物车。

代码实现

1、点击[加入购物车]

或者[+]按钮,页面发送ajax请求,请求服务端,将菜品或者套餐添加到购物车

2、点击购物车图标,页面发送ajax请求,请求服务端查询购物车中的菜品和套餐

3、点击清空购物车按钮,页面发送ajax请求,请求服务端来执行清空购物车操作

开发购物车功能,其实就是在服务端编写代码去处理前端页面发送的这3次请求即可。

准备工作

在开发业务功能前,先将需要用到的类和接口基本结构创建好:

●实体类ShoppingCart(直接从课程资料中导入即可)

●Mapper接口ShoppingCartMapper

●业务层接口ShoppingCartService

●业务层实现类ShoppingCartServicelmpl

●控制层ShoppingCartController

controller

@PostMapping("/add")  
public R<ShoppingCart> add(@RequestBody Shopping  
    //设置用户id  
    Long currentId = BaseContext.getCurrentId();  
    shoppingCart.setUserId(currentId);  
  
    //查询当前商品是否在购物车里面  
    Long dishId = shoppingCart.getDishId();   //  
    LambdaQueryWrapper<ShoppingCart> queryWrappe  
  
    queryWrapper.eq(ShoppingCart::getUserId, sho  
  
    if (dishId != null) {  
        //参加到购物车的是菜品  
        queryWrapper.eq(ShoppingCart::getDishId,  
    } else {  
        queryWrapper.eq(ShoppingCart::getSetmeal  
    }  
  
    ShoppingCart one = shoppingCartService.getOn  
    if (one != null) {  
        //如果已经存在只需要商品数量增加即可  
        Integer number = one.getNumber();  
        one.setNumber(number+1);  
        shoppingCartService.updateById(one);  
    } else {  
        //如果不存在,则添加购物车,数量默认就是1  
        shoppingCart.setNumber(1);  
        shoppingCartService.save(shoppingCart);  
        one=shoppingCart;  
    }  
  
  
    //不存在则添加到购物车  
    return R.success(one);  
  
}

查看购物车

* 
 @GetMapping("/list")  
 public R<List<ShoppingCart>> listR() {  
     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);  
 }

用户下单

需求分析

数据模型

用户下单业务对应的数据表为orders表和order_detail表:

  • orders:订单表
  • order_detail:订单明细表

在开发代码之前,需要梳理一下用户下单操作时前端页面和服务端的交互过程:1、在购物车中点击

去结算按钮,页面跳转到订单确认页面

2、在订单确认页面,发送ajax请求,请求服务端获取当前登录用户的默认地址

3、在订单确认页面,发送ajax请求,请求服务端获取当前登录用户的购物车数据

4、在订单确认页面点击去支付去支付按钮,发送ajax请求,请求服务端完成下单操作

开发用户下单功能,其实就是在服务端编写代码去处理前端页面发送的请求即可。

准备工作

在开发业务功能前,先将需要用到的类和接口基本结构创建好:

实体类Orders、OrderDetail (直接从课程资料中导入即可)

Mapper接口OrderMapper、OrderDetailMapper

业务层接口 OrderService、OrderDetailService

业务层实现类OrderServicelmpl、OrderDetailServicelmpl

控制层OrderController、OrderDetailController

相关文章
|
6月前
|
Java 关系型数据库 MySQL
基于SpringBoot华强北二手手机商城系统
基于SpringBoot华强北二手手机商城系统
|
5月前
|
前端开发 Java API
苍穹外卖开发心得(上)
苍穹外卖开发心得(上)
235 5
|
5月前
|
缓存 JavaScript Java
苍穹外卖开发心得(下)
苍穹外卖开发心得(下)
129 5
|
5月前
|
JSON 前端开发 Java
瑞吉外卖业务开发(2)
瑞吉外卖业务开发
48 3
|
5月前
|
运维 前端开发 测试技术
瑞吉外卖业务开发(1)
瑞吉外卖业务开发
72 3
|
5月前
|
存储 JSON 前端开发
瑞吉外卖业务开发(3)
瑞吉外卖业务开发
44 1
|
6月前
|
搜索推荐 前端开发 Java
酒水商城|基于Springboot实现酒水商城系统
酒水商城|基于Springboot实现酒水商城系统
|
6月前
|
搜索推荐 前端开发 Java
酒水推荐商城|基于Springboot实现酒水商城系统
酒水推荐商城|基于Springboot实现酒水商城系统
|
SQL 缓存 JSON
瑞吉外卖笔记
这是一份写给自己的笔记,主要记录瑞吉外卖项目中自己没有了解过的知识点。我将按照功能来分别解析
725 1
|
负载均衡 Java 数据库连接
瑞吉外卖项目
瑞吉外卖项目
98 0