当前位置: 首页 > news >正文

黑马瑞吉外卖之菜品信息的修改

黑马瑞吉外卖之菜品信息的修改

首先来看前端页面。
首先这个按钮从这里开始
在这里插入图片描述
然后转到下面的调用
在这里插入图片描述
到这里其实就是转到了另外的一个界面,就是我们的add.html。
那这个页面其实就是大致长这样的一个样子。

在这里插入图片描述
然后这里面其实可以需要的是进行一些数据的回显。其实这里的分类是已经调用到了。因为我们之前写过有关分类的后端代码。
我们首先去看前端给到后端的请求。其实我们可以大致浏览一下这个add.html的大致构造。

如下,看前面这一部分就是我们的页面的表单框的主要设计。这里还是进行了数据绑定。
在这里插入图片描述

具体的还是绑定到了属性数据。具体得属性数据还是定义在我们的vue组件的data下面,下面我么来看。

那么我们可以定位到下面这里的属性。
可以看到这里分类的展示,其实是遍历这个dishList里面的数据。这个dishList定义在vue的data数据模型里面。我们可以找到它。

在这里插入图片描述
在这里插入图片描述
然后我们在下面看,其实这里挂载了方法吗,也就是当我们打开这个页面的时候,这个方法会自动执行。我们先来看第一个。

在这里插入图片描述
然后这个方法其实就是具体写道了这里。我们可以看到这里还是传入了参数tyoe=1,这是比较熟悉的,传入1就是要找的就是菜品的分类。
在这里插入图片描述
回忆一下,所以我们打开数据库的这个分类表去看看,你看这里就是我们的分类,根据type的值来区分是套餐的分类还是菜品的分类。所以这样就十分清楚了。
在这里插入图片描述
然后我们点开这个方法去看看。
还是主要写在一个js里面,这里其实我们之前看过,就是分类的后端代码。

在这里插入图片描述
再次简单摘录下来。

 @GetMapping("list")
    public R_<List<Category>> list(Category category)
    {
//        条件构造器
        LambdaQueryWrapper<Category> QueryWrapper = new LambdaQueryWrapper<>();
//        添加条件
        QueryWrapper.eq(category.getType()!=null,Category::getType,category.getType());
//添加排序条件
        QueryWrapper.orderByAsc(Category::getSort).orderByDesc(Category::getUpdateTime);
        List<Category> list = categoryService.list(QueryWrapper);

       return  R_.success(list);
    }

所以我们的这个分类的其实已经完成了,所以它可以正常的展示
在这里插入图片描述
然后我们还是去看前端页面调用的方法,来看看这些数据的会先的情况要求。

然后紧接着划到下面,我们看到下面的init这里面的方法,其实这里还是调用了方法,然后将id传进去,
在这里插入图片描述
我们点进去这个方法。
所以还是写在来一个js里面,再看上面的其实这里请求是要求我们获取到数据模型中的属性。我们应该注意到除了基本的菜品数据还有具体的口味数据。这些数据都赋给了这些数据模型,然后其实这些数据模型还是和上面我们找到的dishlist一样,和表单那里进行了数据模型的绑定。
在这里插入图片描述
那么现在我们思路明确了,然后就可以进行后端逻辑代码的开发。
于是我们应该想到,我们应该自己定义一个查询的方法,将菜品和具体的口味信息的数据都封装进去。注意这里我们做的是查询到具体的信息然后回显。

那么我们班现在可以在service这里重新定义方法,作为扩展的方法。

package com.jgdabc.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.jgdabc.entity.dto.DishDto;
import com.jgdabc.entity.Dish;

public interface DishService extends IService<Dish> {
//新增菜品,同时插入口味数据

    /**
     * 这个是扩展功能,在我们保存菜品数据的时候,在口味表里面也插入改变的数据
     * @param dishDto
     */
   
//    根据id来查询菜品信息和对应的口味信息
    public DishDto getByIdWithFlavor(Long id);

   
}

然后呢,我们具体的去实现。
先把这个注入进来。
在这里插入图片描述

这里我们还是需要dto来进行属性的拷贝。

  @Override
    public DishDto getByIdWithFlavor(Long id) {
//        先查询菜品的基本信息(根据id查询基本的菜品信息)
        Dish dish = this.getById(id);
//引入dto用于扩展属性
        DishDto dishDto = new DishDto();
//这里进行了属性拷贝
        BeanUtils.copyProperties(dish,dishDto);
//        查询菜品对应的口味信息
//添加条件
        LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DishFlavor::getDishId,dish.getId());
        List<DishFlavor> list = dishFlavorService.list(queryWrapper);
        //赋值口味数据
        dishDto.setFlavors(list);
        return  dishDto;
    }

然后我们就去Controller层调用这个方法

  @GetMapping("/{id}")
    public R_<DishDto> get(@PathVariable Long id)
    {

        DishDto dishDto = dishService.getByIdWithFlavor(id);
        if(dishDto!=null)
        {
            return  R_.success(dishDto);
        }
        else
        {
            return  R_.error("没有找到菜品信息");
        }


    }

这样就做到了菜品信息和口味数据的回显。

其实还需要将图片的数据回显,这样就涉及到下载图片的后端功能。其实下载图片我们之前已经开发过了。
前端页面就进行了对图片下载的方法的请求,其实还是调用到我们之前下载图片的代码。
在这里插入图片描述

文件下载的代码

 /**
     * 文件下载
     * @param name
     * @param response
     */
    @GetMapping("/download")
    public void download(String name, HttpServletResponse response) throws IOException {
//        输入流,通过输入流读取文件内容
        FileInputStream fileInputStream = new FileInputStream(new File(basepath) + name);

//        输出流,通过输出流将文件写回到浏览器
//        要向浏览器写回数据,所以通过response响应对象进行写回
        ServletOutputStream outputStream = response.getOutputStream();
//       设置响应类型

        response.setContentType("image/jpeg");
        int len=0;
        byte[] bytes = new byte[1024];
        while((len=fileInputStream.read(bytes))!=-1)
       {
          outputStream.write(bytes,0,len);
          outputStream.flush();
       }
//      关闭资源
      outputStream.close();
      fileInputStream.close();


    }

这样我们的菜品和口味的数据就可以进行完整的回显了。
需要注意的就是图片的这个回显就是我们之前写过的,要结合到文件的上传,文件上传的其中的一个转储,这个路径一个要写对。路径写在了yml文件配置当中。

下面还是给出文件上传的代码截图
在这里插入图片描述
然后就是后端的对修改保存的功能的开发,其实和数据回显哪里一样,我们一样需要考虑到口味数据,我们需要在保存菜品的时候同时还需要保存到口味数据。

我们再去看一下前端的这个请求过程。我们主要关注到数据的修改保存提交,所以我们直接看到这里。
在这里插入图片描述

这个方法其实还是写在了一个js里面。

在这里插入图片描述

通过这两段其实我们就基本明白这个请求的来路。其实我们在浏览器或者代码简单尝试接收参数的调试的话,我们也可以看到前端提交过来哪些数据,已经请求方法和路径这些关键信息。

所以我们现在还是去自定义一个修改保存的方法。我们还是在service去扩展。
我们首先在dishservice里面库欧战一个自定义的方法。就是下面这样。
在这里插入图片描述
然后我们具体去实现。
我们在保存菜品口味的时候需要将对应的菜品口味关联到菜品。
我们尝试一次提交在浏览器的控制台观察数据,这个口味数据这里我们是可以提交未空列表的,所以我们后面做出一个处理就是如果提交口味数据为null的话,那么就不更新口味数据就好了。其实这取决于自己的处理逻辑。值得注意的是我们的口味数据需要关联到菜品。我们看菜品的基本信息是有id的,我们可以先将菜品添加保存,然后给DishFlavor设置对应的菜品id,那么我们就可以去用流的方式去遍历处理口味,然后将每个口味对应的关联菜品的id set上去。然后呢,我们对对应的口味数据进行批量保存就可以了,就是这样的一个处理逻辑。
在这里插入图片描述
还需要注意的是,我们要求的是需要的保存菜品的时候同时保存口味,那么这里其实应该去用到事务。我们必须去开启事务支持。万一在保存菜品和口味的这两个操作中某个过程挂掉或者出现问题的话,那么如果只有一个操作正常进行的话,这样其实是不符合逻辑的。所以这样就需要开启事务了。
其实类似这样的操作,都应该去开启事务。
启动类

在这里插入图片描述

代码如下。

 @Override
    @Transactional
    public void updateWithFlavor(DishDto dishDto) {
//        更新dish表
        this.updateById(dishDto);
//        更新口味表dish_flavor
        /**
         * 可以有这样一个操作逻辑
         * 就是先清理掉口味表数据,然后在重新插入更新的数据
         */
//       获取到口味数据的条件表达式
        LambdaQueryWrapper<DishFlavor> dishFlavorLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dishFlavorLambdaQueryWrapper.eq(DishFlavor::getDishId,dishDto.getId());


//添加到新的数据
//        获取到前端提交过来的口味数据
        List<DishFlavor> flavors = dishDto.getFlavors();
//
        if (flavors!=null)
        {
            dishFlavorService.remove(dishFlavorLambdaQueryWrapper);
            flavors = flavors.stream().map((item)->
            {
                item.setDishId(dishDto.getId());
                return item;
            }).collect(Collectors.toList());
            dishFlavorService.saveBatch(flavors);


        }


    }

这是我们serviceimpl开发的方法。

接下来我们去Controller里面去调用这个方法。

  修改菜品
    @PutMapping
    public R_<String> update(@RequestBody DishDto dishDto) {

        log.info(dishDto.toString());
        dishService.updateWithFlavor(dishDto);
        return R_.success("修改菜品成功");
    }

这样就可以了。

相关文章:

  • 【Vue 基础知识】v-for的使用和注意事项
  • LeetCode Cookbook 数组习题(8)
  • Java新手小白入门篇 SpringBoot项目的构建
  • 第十一届中国创新创业大赛浙江赛区暨第九届浙江省“火炬杯”创新创业大赛-新一代信息技术行业总决赛
  • kuangbin专题六 最小生成树(2022.9.3)
  • C++s简单实现Scoket编程
  • 做一个物联网温湿度传感器(一)SHT30传感器介绍
  • Sublime Text 最简单的更换主题和字体颜色的办法
  • 通过vue ui方式构建vue+electron项目
  • 2022最新一线大厂Java八股文合集PDF版震撼开源,堪称史上最强
  • 5.13一行代码就能解决的算法题
  • 序列查询新解
  • 5.10如何调度考生的座位
  • 基于retas的动漫动画制作与设计
  • 【Lua 入门基础篇(十)】文件I/O
  • Docker: 容器互访的三种方式
  • github指令
  • javascript从右向左截取指定位数字符的3种方法
  • leetcode46 Permutation 排列组合
  • Meteor的表单提交:Form
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • PHP的Ev教程三(Periodic watcher)
  • spring boot 整合mybatis 无法输出sql的问题
  • Sublime text 3 3103 注册码
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • vue总结
  • windows下如何用phpstorm同步测试服务器
  • 从重复到重用
  • 机器学习 vs. 深度学习
  • 七牛云假注销小指南
  • 浅谈Golang中select的用法
  • 区块链分支循环
  • 如何进阶一名有竞争力的程序员?
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 微信支付JSAPI,实测!终极方案
  • 正则表达式小结
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • 第二十章:异步和文件I/O.(二十三)
  • #laravel 通过手动安装依赖PHPExcel#
  • #pragam once 和 #ifndef 预编译头
  • (C#)获取字符编码的类
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (十二)python网络爬虫(理论+实战)——实战:使用BeautfulSoup解析baidu热搜新闻数据
  • (转)EOS中账户、钱包和密钥的关系
  • (转)ORM
  • .net core 3.0 linux,.NET Core 3.0 的新增功能
  • .NET Core使用NPOI导出复杂,美观的Excel详解
  • .Net Memory Profiler的使用举例
  • .net MVC中使用angularJs刷新页面数据列表
  • .net refrector
  • .net(C#)中String.Format如何使用
  • .NET/C# 检测电脑上安装的 .NET Framework 的版本
  • .NET6使用MiniExcel根据数据源横向导出头部标题及数据
  • .net反编译工具
  • @manytomany 保存后数据被删除_[Windows] 数据恢复软件RStudio v8.14.179675 便携特别版...