瑞吉外卖项目:新增菜品与菜品分页查询

目录

一. 新增菜品

1.1 需求分析

1.2 数据模型

1.3 代码实现

二. 菜品分页查询

2.1 需求分析

2.2 代码编写


一. 新增菜品

1.1 需求分析

后台系统可以管理菜品信息,通过新增功能来添加新的菜品,在添加菜品时需要选择当前菜品所属的菜品分类。

此外还需要上传菜品图片,在移动端会按照菜品分类来展示对应的菜品信息。

瑞吉外卖项目:新增菜品与菜品分页查询_第1张图片

1.2 数据模型

设计两张表菜品表与菜品口味表,添加某个菜品的口味做法时,需要加入菜品口味表中。

菜品表(dish)

瑞吉外卖项目:新增菜品与菜品分页查询_第2张图片

菜品口味表(dish_flavor)

瑞吉外卖项目:新增菜品与菜品分页查询_第3张图片

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

  1. 页面(backend/page/food/add.html)发送aiax请求,请求服务端获取菜品分类数据并展示到下拉框中
  2. 页面发送请求进行图片上传,请求服务端将图片保存到服务器
  3. 页面发送请求进行图片下载,将上传的图片进行回显
  4. 点击保存按钮,发送ajax请求,将菜品相关数据以ison形式提交到服务端

dishFlavor.java

package com.itheima.reggie.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * 菜品口味
 */
@Data
public class DishFlavor implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;

    //菜品id
    private Long dishId;

    //口味名称
    private String name;

    //口味数据list
    private String value;

    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;

    @TableField(fill = FieldFill.INSERT)
    private Long createUser;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;

    //是否删除
    private Integer isDeleted;

}

填好所需数据发的添加菜品的mock格式如下:

{
  "name": "test1",
  "price": 1200,
  "code": "",
  "image": "bbbf37f0-00c1-4dff-8825-b79506ad33cf.jpg",
  "description": "sdfg",
  "status": 1,
  "categoryId": "1397844263642378242",
  "flavors": [
    {
      "name": "辣度",
      "value": "[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]",
      "showOption": false
    },
    {
      "name": "温度",
      "value": "[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]",
      "showOption": false
    }
  ]
}

注意:Dish(这里)这个对象中并没有封装口味对象,所以我们需要对上面的JSON数据重新封装。

DishDTO.java

package com.itheima.reggie.dto;

import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;

@Data
public class DishDto extends Dish {

    /** 菜品口味*/
    private List flavors = new ArrayList<>();

    private String categoryName;

    private Integer copies;
}

什么是DTO?

Data Transfer Object,数据传输对象,用于展示层与服务层之间的数据传输

1.3 代码实现

DishServiceImpl.java中添加如下代码:

package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.mapper.DishMapper;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author jektong
 * @date 2022年05月10日 20:15
 */
@Service
public class DishServiceImpl extends ServiceImpl implements DishService {

    @Resource
    private DishFlavorService dishFlavorService;

    /**
     * 新增菜品,同时插入菜品对应的口味数据
     * @param dishDto
     */
    @Override
    @Transactional
    public void saveWithFlover(DishDto dishDto) {
        // 保存菜品基本信息到菜品表dish
        this.save(dishDto);
        // 获取菜品ID
        Long dishId = dishDto.getId();
        List flavors = dishDto.getFlavors();
        // 菜品ID设置进口味中
        flavors = flavors.stream().map((item)->{
            item.setDishId(dishId);
            return item;
        }).collect(Collectors.toList());

        // 菜品口味数据保存
        dishFlavorService.saveBatch(flavors);
    }
}

由于以上代码涉及多次对数据库的操作,所以需要加上注解:

@Transactional并需要在启动类上开启事务注解@EnableTransactionManagement才可生效

package com.itheima.reggie;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * @author tongbing
 * @date 2022/4/21
 */
@Slf4j
@SpringBootApplication
@ServletComponentScan
@EnableTransactionManagement
public class ReggieApplication {
    public static void main(String[] args) {
        SpringApplication.run(ReggieApplication.class,args);
        log.info("reggie======>启动成功");
    }
}

DishController调用:

package com.itheima.reggie.controller;

import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
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;

import javax.annotation.Resource;

/**
 * @author jektong
 * @date 2022年05月16日 22:22
 */
@RestController
@Slf4j
@RequestMapping("/dish")
public class DishController {

    @Resource
    private DishService dishService;

    /**
     * 新增菜品,同时插入菜品对应的口味数据
     * @param dishDto
     * @return R
     */
    @PostMapping
    public R save(@RequestBody DishDto dishDto){
        log.info("DishDTO===>{}",dishDto);
        dishService.saveWithFlover(dishDto);
        return R.success("菜品添加成功");
    }
}

二. 菜品分页查询

2.1 需求分析

分页展示菜品数据如下图:

瑞吉外卖项目:新增菜品与菜品分页查询_第4张图片

 交互流程

  1. 页面(backend/page/food/listhtml)发送ajax请求,将分页查询参数(page,pageSize,name)提交到服务端,获取分页数据
  2. 页面发送请求,请求服务端进行图片下载,用于页面图片展示

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

2.2 代码编写

DishController代码:

    @GetMapping("/page")
    public R page(int page, int pageSize,String name){
        log.info("page={},pageSize={},name={}", page, pageSize, name);
        // 构造分页构造器
        Page pageInfo = new Page(page, pageSize);
        // 因为前端需要展示分类的名称,所以封装成DishDto对象
        Page dishDtoPage = new Page(page, pageSize);
        // 构造条件
        LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper();
        queryWrapper.like(StringUtils.isNotEmpty(name), Dish::getName, name);
        // 添加排序
        queryWrapper.orderByDesc(Dish::getUpdateTime);
        // 执行查询
        dishService.page(pageInfo, queryWrapper);
        // 进行对象拷贝,去除之前已经查出来的集合
        BeanUtils.copyProperties(pageInfo,dishDtoPage,"records");

        List records = pageInfo.getRecords();
        List list = records.stream().map((item)->{
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(item,dishDto);
            // 获取categoryId
            Long categoryId = item.getCategoryId();
            // 给categoryName赋值
            Category category = categoryService.getById(categoryId);
            // 需要对查出来的分类做判断可能有的菜品没有分类
            if(category!=null){
                dishDto.setCategoryName(category.getName());
            }
            return dishDto;
        }).collect(Collectors.toList());
        dishDtoPage.setRecords(list);
        return R.success(dishDtoPage);
    }

以上代码需要注意的是需要展示分类的名称,所以封装成DishDto对象进行返回就需要使用对象的拷贝,以及查出来的分类需要判空操作。

你可能感兴趣的:(黑马项目实战:《瑞吉外卖项目》,java,spring)