瑞吉外卖功能完善

news2024/9/28 21:28:12

文章目录

  • 获取源码
  • 1、后台管理——菜品起售停售
    • 前端请求数据分析
    • 编写方法
  • 2、后台管理——菜品删除
    • 前端请求数据分析
    • 编写方法
  • 3、后台管理——修改套餐
    • 前端请求分析
    • 方法一:完成点击修改时数据的回显
    • 方法二:修改套餐
  • 4、后台管理——启停售套餐
    • 前端请求分析
    • 编写方法
  • 5、后台管理——订单明细分页查询
    • 前端请求分析
    • 编写方法
    • 运行结果
  • 6、后台管理——订单操作
    • 前端请求分析
    • 编写方法
  • 7、客户端——退出登录
    • 前端请求分析
    • 编写方法
  • 8、客户端——购物车商品减少
    • 前端请求分析
    • 编写方法
  • 9、客户端——查看订单
    • 前端请求分析
    • 准备工作
    • 编写方法
    • 运行结果
  • 10、客户端——订单完成后再来一单
    • 前端请求分析
    • 编写方法

本项目是基于自学b站中 黑马程序员 的瑞吉外卖项目:视频链接: 黑马程序员Java项目实战《瑞吉外卖》,轻松掌握springboot + mybatis plus开发核心技术的真java实战项目_哔哩哔哩_bilibili

自己把视频中一些没实现的功能给实现了;本人技术可能不到位,笔记仅供参考学习使用;
本人自己把视频中老师没讲的功能都给实现了

获取源码

1、后台管理——菜品起售停售

前端请求数据分析

  • 单个停售起售
    在这里插入图片描述

    在这里插入图片描述

  • 批量起售停售
    在这里插入图片描述
    在这里插入图片描述
    通过请求分析,我们可以看到单个启停售与批量启停售都是请求的同一个地址。传的status是个RestFul风格,ids是个集合。

编写方法

  • @PostMapping(“/status/{status}”):请求地址

  • @PathVariable:绑定占位符

  • @RequestParam:前端参数名与后端要一致,用于接收前端传过来的集合

    /**
     * 菜品启用停售
     *
     * @param status
     * @param ids
     * @return
     */
    @PostMapping("/status/{status}")
    public R<String> status( @PathVariable int status,@RequestParam List<Long> ids ) {
        log.info("status:{}=========ids:{}", status, ids);
    
        List<Dish> dishList = dishService.listByIds(ids);
        for (Dish dish : dishList) {
            dish.setStatus(status);
        }
    
        dishService.updateBatchById(dishList);
    
        return R.success("菜品状态修改成功");
    }
    

2、后台管理——菜品删除

前端请求数据分析

  • 删除单个菜品
    在这里插入图片描述
  • 批量删除菜品
    在这里插入图片描述
    这里可以看到无论是删除单个菜品还是批量删除菜品都是请求的同一个地址,所以这里也是只需要编写一个方法即可

编写方法

/**
 * 删除菜品
 * @param ids
 * @return
*/
@DeleteMapping
public R<String> delete(@RequestParam List<Long> ids ) {
    log.info("要删除的菜品id:{}",ids);
    dishService.removeByIds(ids);
    return R.success("删除菜品成功");
}

3、后台管理——修改套餐

前端请求分析

  • 当单击修改套餐时,我们发现有一个请求404所以我们只需要完成这一个请求的方法编写即可
    在这里插入图片描述

  • 当我们保存修改时也有一个请求404,需要完成
    在这里插入图片描述

方法一:完成点击修改时数据的回显

  • Servicer层

    /**
     * 根据ID查询套餐,同时查询关联额菜品数据
     * @param id
     * @return
     */
    public SetmealDto setmealDishById(Long id);
    
  • impl层

    /**
     * 根据ID查询套餐,同时查询关联额菜品数据
     * @param id
     * @return
     */
    @Override
    public SetmealDto setmealDishById(Long id){
        //获取套餐ID
        Setmeal setmeal = this.getById(id);
    
        //对象拷贝
        SetmealDto setmealDto = new SetmealDto();
        BeanUtils.copyProperties(setmeal,setmealDto);
    
        //构造条件构造器
        LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
    
        //查询套餐关联的菜品
        queryWrapper.eq(SetmealDish::getSetmealId,id);
        List<SetmealDish> list = setmealDishService.list(queryWrapper);
    
        //设置套餐关联的菜品
        setmealDto.setSetmealDishes(list);
    
        return setmealDto;
    }
    
  • controller层

    /**
     * 根据ID查询套餐以及关联的菜品
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public R<SetmealDto> get(@PathVariable Long id ){
        log.info("根据ID查询套餐信息ID:{}",id);
    
        SetmealDto setmealDto = setmealService.setmealDishById(id);
        return R.success(setmealDto);
    }
    

方法二:修改套餐

  • service层

    /**
     * 更新套餐信息同时更新关联的菜品数据
     * @param setmealDto
     */
    public void updateSetmealDish(SetmealDto setmealDto);
    
  • impl层:这里操作了两张表加上事物

    /**
    * 更新套餐信息同时更新关联的菜品数据
    * @param setmealDto
    */
    @Transactional
    @Override
    public void updateSetmealDish( SetmealDto setmealDto ) {
       //更新套餐数据
       this.updateById(setmealDto);
    
       //获取套餐ID
       Long setmealId = setmealDto.getId();
    
       //构造条件构造器
       LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
    
       //删除套餐关联的菜品
       queryWrapper.eq(SetmealDish::getSetmealId, setmealId);
       setmealDishService.remove(queryWrapper);
    
       //添加新的套餐关联菜品
       List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
    
       //菜品关联套餐ID
       setmealDishes = setmealDishes.stream().map(( item ) -> {
           item.setSetmealId(setmealId);
           return item;
       }).collect(Collectors.toList());
    
       //保存套餐和菜品的关联信息,操作setmeal_dish,执行insert操作
       setmealDishService.saveBatch(setmealDishes);
    }
    
  • controller层

    /**
    * 更新套餐信息同时更新关联的菜品数据
    * @param setmealDto
    * @return
    */
    @PutMapping
    public R<String > update(@RequestBody SetmealDto setmealDto){
        log.info("修改套餐数据:",setmealDto);
        setmealService.updateSetmealDish(setmealDto);
        return R.success("修改成功");
    }
    

4、后台管理——启停售套餐

前端请求分析

  • 停售起售单个套餐
    在这里插入图片描述
    在这里插入图片描述
  • 批量起停售套餐
    在这里插入图片描述
    在这里插入图片描述
    看到单个启停售与批量启停售使用的都是一个请求,所以我们这里创建一个方法即可完成

编写方法

  • 此方法与菜单启停售方法半斤八两
    /**
     * 套餐启停售
     * @param status
     * @param ids
     * @return
    */
    @PostMapping("/status/{status}")
    public R<String> status(@PathVariable int status,@RequestParam List<Long> ids){
        log.info("修改套餐状态:status:{}-----------ids:{}",status,ids);
        List<Setmeal> setmeals = setmealService.listByIds(ids);
    
        //跟新状态
        setmeals=setmeals.stream().map((item)->{
            item.setStatus(status);
            return item;
        }).collect(Collectors.toList());
    
        setmealService.updateBatchById(setmeals);
    
        return R.success("套餐状态修改成功");
    }
    
    

5、后台管理——订单明细分页查询

前端请求分析

  • 当我们单击订单明细子功能时发送了一个请求,同时还发现通过参数请求时也发送的是同一个请求,所以我们只需要在后端编写一个方法来处理就可以了
    • 点击订单明细子功能
      在这里插入图片描述
    • 添加时间参数 在这里插入图片描述
    • 添加关键字
      在这里插入图片描述
    • 添加关键字同时添加时间参数 在这里插入图片描述

编写方法

  • @DateTimeFormat:接收前端数据

    • pattern:用于指定时间格式
    /**
     * 分页查询订单信息
     * @param page
     * @param pageSize
     * @param number
     * @param beginTime
     * @param endTime
     * @return
     */
    @GetMapping("/page")
    public R<Page<Orders>> page( int page, int pageSize, Long number,  @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime beginTime,@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime){
        log.info("订单明细查询");
    
        //分页构造器
        Page<Orders> ordersPage = new Page<>(page,pageSize);
    
        //条件构造器
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
    
        //添加查询条件number模糊查询
        queryWrapper.like(number!=null,Orders::getNumber,number);
    
        //添加查询条件起始时间
        queryWrapper.ge(beginTime!=null,Orders::getOrderTime,beginTime);
        //添加查询条件结束时间
        queryWrapper.le(endTime!=null,Orders::getOrderTime,endTime);
    
        //添加排序条件
        queryWrapper.orderByDesc(Orders::getOrderTime);
    
        ordersService.page(ordersPage,queryWrapper);
    
        return R.success(ordersPage);
    }
    

运行结果

在这里插入图片描述

6、后台管理——订单操作

前端请求分析

  • 通过请求分析,可以得到数据是以JSON传送的,后端我们可以使用 Orders 对象接收
    在这里插入图片描述
    在这里插入图片描述

编写方法

/**
 * 订单状态跟新
 * @param orders
 * @return
 */
@PutMapping
public R<String> update(@RequestBody Orders orders){
    log.info("订单操作orders:+{}",orders);

    //更新状态
    ordersService.updateById(orders);

    return R.success("状态更新成功");
}

7、客户端——退出登录

前端请求分析

  • 前端并没有传参,所以后端只需要把Session移除即可
    在这里插入图片描述

编写方法

/**
 * 用户退出登录
 * @param session
 * @return
 */
@PostMapping("/loginout")
public R<String > logOut( HttpServletRequest session){
    log.info("用户退出登录session:{}",session);

    session.getSession().removeAttribute("user");

    return R.success("退出成功");
}

8、客户端——购物车商品减少

前端请求分析

  • 从前端请求可以看到参数传递的形式为JSON,所以后端我们用 ShoppingCart 实体类接收参数
    在这里插入图片描述
    在这里插入图片描述

编写方法

  • service层

    /**
     * 购物车修改
     * @param shoppingCart
     * @return
     */
    public ShoppingCart sub(@RequestBody ShoppingCart shoppingCart);
    
  • impl层

    /**
     * 购物车修改
     * @param shoppingCart
     * @return
     */
    @Override
    public ShoppingCart sub( ShoppingCart shoppingCart ) {
        //获取用户ID
        Long userId = BaseContext.getCurrentId();
    
        //获取菜品ID
        Long dishId = shoppingCart.getDishId();
    
        ShoppingCart one=null;
    
        //条件构造器
        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
        //指定是哪个用户的购物车
        queryWrapper.eq(ShoppingCart::getUserId,userId);
    
        if (dishId!=null){
            //修改的是菜品数量
            queryWrapper.eq(ShoppingCart::getDishId,dishId);
            one = this.getOne(queryWrapper);
        }else{
            //修改的是套餐数量
            queryWrapper.eq(ShoppingCart::getSetmealId,shoppingCart.getSetmealId());
            one = this.getOne(queryWrapper);
        }
    
        //如果购物车中的数量大于1份,则相应的套餐数量减一
        one.setNumber(one.getNumber()-1);
        if(one.getNumber()>0){
            //如果还有套餐则更新数据
            this.updateById(one);
        }else{
            //如果购物中数量为0则删除
            this.removeById(one);
        }
    
        return one;
    }
    
  • controller层

    /**
     * 购物车修改
     * @param shoppingCart
     * @return
     */
    @PostMapping("/sub")
    public R<ShoppingCart> sub(@RequestBody ShoppingCart shoppingCart){
        log.info("购物车修改shoppingCart:{}",shoppingCart);
    
        ShoppingCart one = shoppingCartService.sub(shoppingCart);
    
        return R.success(one);
    }
    

9、客户端——查看订单

前端请求分析

  • 请求中带有两个参数,后端需要接收在这里插入图片描述

准备工作

在编写方法前,需要导入 OrdersDto
在这里插入图片描述

编写方法

/**
 * 用户最近订单查询
 * @param page
 * @param pageSize
 * @return
 */
@GetMapping("/userPage")
public R<Page<Orders>> userPage( int page, int pageSize ){
    log.info("用户订单分页");

    //获取用户ID
    Long userID = BaseContext.getCurrentId();

    //分页构造器
    Page<Orders> pageInfo = new Page<>(page,pageSize);

    //条件构造器
    LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();

    //指定用户的订单
    queryWrapper.eq(Orders::getUserId,userID);

    //添加排序条件
    queryWrapper.orderByDesc(Orders::getOrderTime);

    ordersService.page(pageInfo,queryWrapper);



    return R.success(pageInfo);
}

运行结果

在这里插入图片描述
在这里插入图片描述

10、客户端——订单完成后再来一单

前端请求分析

  • 当订单完成时可以选择买一个最近相同菜品/套餐
    在这里插入图片描述
    在这里插入图片描述

  • 分析前端请求可知,该请求中带有一个参数,我们后端可以使用 Orders 实体类接收参数
    在这里插入图片描述
    在这里插入图片描述

编写方法

  • service层

    /**
     * 再来一单
     * @param orders
     */
    public void again(Orders orders);
    
  • impl层

    /**
     * 再来一单
     * @param orders
     */
    @Override
    public void again( Orders orders ) {
        //条件构造器
        LambdaQueryWrapper<Orders> ordersLambdaQueryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<OrderDetail> orderDetailLambdaQueryWrapper = new LambdaQueryWrapper<>();
    
        //添加订单ID条件
        ordersLambdaQueryWrapper.eq(Orders::getId,orders.getId());
    
        //添加指定订单的订单明细条件
        orderDetailLambdaQueryWrapper.eq(OrderDetail::getOrderId,orders.getId());
    
        //获取订单
        Orders one = this.getOne(ordersLambdaQueryWrapper);
    
        //获取订单明细
        List<OrderDetail> orderDetails = orderDetailService.list(orderDetailLambdaQueryWrapper);
    
        long orderId = IdWorker.getId();//订单号
    
        //修改订单明细信息
        orderDetails=orderDetails.stream().map((item)->{
            item.setId(null);   //移除原有的订单明细ID
            item.setOrderId(orderId);
            return item;
        }).collect(Collectors.toList());
    
        //修改订单信息
        one.setNumber(String.valueOf(orderId));
        one.setId(orderId);
        one.setOrderTime(LocalDateTime.now());
        one.setCheckoutTime(LocalDateTime.now());
        one.setStatus(2);
    
        //向订单表插入一条数据
        this.save(one);
    
        //向订单明细表插入数据,多条数据
        orderDetailService.saveBatch(orderDetails);
    
    }
    
  • controller层

        /**
         * 再来一单
         * @param orders
         * @return
         */
        @PostMapping("/again")
        public R<String>  again(@RequestBody Orders orders){
            log.info("再来一单orders:",orders);
    
            ordersService.again(orders);
            return R.success("再来一单成功");
        }
    
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/636994.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全国PMO专业人士年度盛会︱2023第十二届PMO大会将于8月在京召开

企业要基业长青就必须持续保持组织活力。企业的内外部环境不会一成不变&#xff0c;顺应变化及时调整变革避免组织出现僵化低效才能在激烈的市场竞争中存活下来。PMO从成立到逐渐发挥越来越强的作用本身即是一种组织变革的过程&#xff0c;从这个意义上来说PMO因组织变革而生&a…

epson L350打印机拆解

卡扣固定 搓纸轮 送纸器

数据库的基本知识---入门前必读

目录 一.认识数据库 二.数据库的分类 三.SQL介绍 3.1SQL是什么 3.2.SQL语言使用方式 总结 &#x1f63d;个人主页&#xff1a;tq02的博客_CSDN博客-C语言,Java,Java数据结构领域博主 &#x1f308;梦的目标&#xff1a;努力学习&#xff0c;打败数据库&#xff0c;拼搏一…

echarts 按需引入解决打包体积过大问题

问题&#xff1a;由于服务器网速特别慢大概100kb打包文件过大导致第一次加载静态文件时特别慢&#xff0c;优化echarts 原先引入的方式和使用&#xff08;导致体积过大&#xff09;&#xff1a; // 引入 echarts 核心模块&#xff0c;核心模块提供了 echarts 使用必须要的接口…

10. Java对象内存布局和对象头

10.1 面试题 ● 说下JUC&#xff0c;AQS的大致流程 ● CAS自旋锁&#xff0c;是获取不到锁就一直自旋吗&#xff1f;CAS和synchronized区别在哪里&#xff0c;为什么CAS好&#xff0c;具体优势在哪里&#xff1f; ● sychronized底层是如何实现的&#xff0c;实现同步的时候用到…

idea导入java web项目带jar

可参考&#xff1a;idea导入Javaweb项目_小黑cc的博客-CSDN博客 配置tomcat 加载项目jar依赖 最后点ok&#xff0c;tomcat启动 jsp页面的项目&#xff0c;必须要加载这两个jar包

windows 服务程序和桌面程序集成(二)服务程序

系列文章目录链接&#xff1a; windows 服务程序和桌面程序集成&#xff08;一&#xff09;概念介绍windows 服务程序和桌面程序集成&#xff08;二&#xff09;服务程序windows 服务程序和桌面程序集成&#xff08;三&#xff09;UDP监控工具windows 服务程序和桌面程序集成&…

OpenLayers.js 入门教程:打造互动地图的入门指南

theme: smartblue 本文简介 戴尬猴&#xff0c;我是德育处主任 本文介绍如何使用 OpenLayers.js (后面简称 ol)。ol 是一个开源 JavaScript 库&#xff0c;可用于在Web页面上创建交互式地图。 ol能帮助我们在浏览器轻松地使用地图功能&#xff0c;例如地图缩放、地图拖动、地图…

双碳目标下DNDC模型建模方法及在土壤碳储量、温室气体排放、农田减排、土地变化、气候变化中的应用

由于全球变暖、大气中温室气体浓度逐年增加等问题的出现&#xff0c;“双碳”行动特别是碳中和已经在世界范围形成广泛影响。国家领导人在多次重要会议上讲到&#xff0c;要把“双碳”纳入经济社会发展和生态文明建设整体布局。同时&#xff0c;提到要把减污降碳协同增效作为促…

数字电子电路绪论

博主介绍&#xff1a;一个爱打游戏的计算机专业学生 博主主页&#xff1a;夏驰和徐策 所属专栏&#xff1a;程序猿之数字电路 1.科技革命促生互联网时代 科技革命对互联网时代的兴起产生了巨大的推动作用。以下是一些科技革命对互联网时代的促进因素&#xff1a; 1. 计算机技…

赢涛智慧工单 v2.4.3 公众号模块版

适用于&#xff1a;入驻加盟、运价查询、申请返礼、工单售后、商标注册、执照申请、汽车保养、年审代办、材料申请、流程审批、贷款申请、废品回收、投诉建议、业务登记、在线督导、购房申请、设备维修、门店报修、信息申请、材料提交、合作咨询、党群服务、入党申请、补贴申领…

内网隧道代理技术(三)之使用SSH端口转发

使用SSH端口转发 SSH介绍 SSH通过网络远程访问主机提供保护&#xff0c;可以对客户端和服务端之间的数据传输进行压缩和加密&#xff0c;有身份验证、SCP、SFTP、和端口转发的功能 SSH转发常用的参数介绍&#xff1a; 参数作用-C请求压缩所有数据-D动态转发、即socks代理-f…

np.meshgrid()与网络表格

目录 数组是如何绘制表格的&#xff1f;分别绘制X和Y图像绘制等高线 数组是如何绘制表格的&#xff1f; 我们先将两个数组传入np.meshgrid()&#xff0c;查看该函数是如何绘制网格的。 import numpy as npx np.linspace(-2, 2, 5) y np.linspace(-2, 2, 5)X, Y np.meshgri…

【无标题】储能电池IEC62619认证 IEC62619测试什么内容

储能电池IEC62619认证 IEC62619测试什么内容 作为专业的民营三方检测、认证服务型的&#xff0c;同时已获得CNAS、CMA、NVLAP、MICOM、A2AL、CPSC、IC、EMSD、NATA、SABS、KOSTEC、 lNSPECCO、E-mark、TUV、CETECOM、EUROFINS、PHOENIX、HOENIX、KTC、ITS、SAA、UL等20多个国内…

在webpack中配置bable

一、什么是bable Babel是一个JavaScript**编译工具**&#xff0c;主要用于在旧浏览器或过时的JavaScript语言版本中转换新的或标准的JavaScript语法和功能。它的主要作用是解决跨浏览器的兼容性问题&#xff0c;让我们能够使用最新的JavaScript特性&#xff0c;而不必担心它们…

一个轻量级Web蜜罐(附下载地址)

Loki 0x01 Why 目标: 抓漏洞. 大概是没有找到啥子开源的符合我预期的蜜罐吧&#xff0c;所以自己动手写了。 0x02 What 想做什么样的蜜罐? 1.便于维护,随开随用,配置简单。 2.Web低仿真即可,且只抓Web流量。 3.不同端口指向不同的页面,响应头配置等。 0x03 How SpringB…

Matlab论文插图绘制模板第102期—分组填充箱线图

在之前的文章中&#xff0c;分享了Matlab箱线图的绘制模板&#xff1a; 填充箱线图的绘制模板&#xff1a; 分组箱线图的绘制模板&#xff1a; 进一步&#xff0c;再来分享一下分组填充箱线图的绘制模板。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据…

DTMultiWindow UE UMG 多窗口插件说明

本插件可以把UMG窗口做为一个系统窗口独立显示。 目录 操作步骤&#xff1a; DT User Widget 说明&#xff1a; 全局蓝图节点说明 &#xff1a; 操作步骤&#xff1a; 1. 创建一个新的UMG&#xff0c;类型选择 DT User Widget 2. 使用传统方式&#xff0c;搭建这个UMG控件。…

深度学习应用篇-自然语言处理[10]:N-Gram、SimCSE介绍,更多技术:数据增强、智能标注、多分类算法、文本信息抽取、多模态信息抽取、模型压缩算法等

【深度学习入门到进阶】必看系列&#xff0c;含激活函数、优化策略、损失函数、模型调优、归一化算法、卷积模型、序列模型、预训练模型、对抗神经网络等 专栏详细介绍&#xff1a;【深度学习入门到进阶】必看系列&#xff0c;含激活函数、优化策略、损失函数、模型调优、归一化…