• 6.套餐管理业务开发


    套餐管理业务开发

    1、准备工作

    准备需要用到的类和接口

    1. 实体类SetmealDish
    2. DTO SetmealDto
    3. Mapper接口SetmealDishMapper
    4. 业务层接口SetmealDishService
    5. 业务层实现类SetmealDishServiceImpl
    6. 控制层SetmealController

    2、新增套餐

    执行流程:

    1. 页面(backend/page/comboladd.html)发送ajax请求,请求服务端获取套餐分类数据并展示到下拉框中
    2. 页面发送ajax请求,请求服务端获取菜品分类数据并展示到添加菜品窗口中
    3. 页面发送ajax请求,请求服务端,根据菜品分类查询对应的菜品数据并展示到添加菜品窗口中
    4. 页面发送请求进行图片上传,请求服务端将图片保存到服务器
    5. 页面发送请求进行图片下载,将上传的图片进行回显
    6. 点击保存按钮,发送ajax请求,将套餐相关数据以json形式提交到服务端

    2.1、查询菜品分类列表

    DishController创建list方法

    /**
     * 根据条件查询对应的菜品数据
     * @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());
        // 查询状态为1的菜品
        queryWrapper.eq(Dish::getStatus, 1);
    
        // 添加排序条件
        queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
    
        List<Dish> list = dishService.list(queryWrapper);
    
        return R.success(list);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2.2、阿里云OSS图片回显(可选)

    修改backend/page/combo/add.html页面以下内容,改成自己的阿里云地址加上图片名称

    image-20220619153241714

    2.3、保存新增信息

    2.3.1、SetmealController

    package com.itheima.reggie.controller;
    
    import com.itheima.reggie.common.R;
    import com.itheima.reggie.dto.SetmealDto;
    import com.itheima.reggie.entity.SetmealDish;
    import com.itheima.reggie.service.SetmealDishService;
    import com.itheima.reggie.service.SetmealService;
    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;
    
    /**
     * @Author: xjhqre
     * @DateTime: 2022/6/19 15:36
     */
    @RequestMapping("/setmeal")
    @RestController
    @Slf4j
    public class SetmealController {
    
        @Autowired
        SetmealService setmealService;
    
        @Autowired
        SetmealDishService setmealDishService;
    
        /**
         * 新增套餐
         * @param setmealDto
         * @return
         */
        @PostMapping
        public R<String> save(@RequestBody SetmealDto setmealDto) {
            log.info("新增套餐信息:{}", setmealDto);
            setmealService.saveWithDish(setmealDto);
            return R.success("添加套餐成功");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    2.3.2、SetmealService

    // 新增套餐,同时需要保存套餐和菜品的关联关系
    void saveWithDish(SetmealDto setmealDto);
    
    • 1
    • 2

    2.3.3、SetmealServiceImpl

    /**
     * 新增套餐,同时需要保存套餐和菜品的关联关系
     * @param setmealDto
     */
    @Override
    @Transactional
    public void saveWithDish(SetmealDto setmealDto) {
        // 保存套餐的基本信息,操作setmeal,执行insert操作
        this.save(setmealDto);
    
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        setmealDishes = setmealDishes.stream().map(item -> {
            item.setSetmealId(setmealDto.getId());
            return item;
        }).collect(Collectors.toList());
    
        // 保存套餐和菜品的关联信息,操作setmeal_dish执行insert操作
        setmealDishService.saveBatch(setmealDishes);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2.4、测试新增套餐

    3、套餐信息分页查询

    执行流程:

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

    3.1、方法一:老师的方法

    SetmealController创建page方法

    /**
     * 套餐信息分页查询
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    public R<Page> page(int page, int pageSize, String name) {
        // 分页构造器对象
        Page<Setmeal> pageInfo = new Page<>(page, pageSize);
        Page<SetmealDto> dtoPage = new Page<>();
    
        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
        // 添加查询条件,根据name进行like模糊查询
        queryWrapper.like(name != null, Setmeal::getName, name);
        // 添加排序条件,根据更新时间降序排序
        queryWrapper.orderByDesc(Setmeal::getUpdateTime);
    
        setmealService.page(pageInfo, queryWrapper);
    
        // 对象拷贝
        BeanUtils.copyProperties(pageInfo, dtoPage, "records");
        List<Setmeal> records = pageInfo.getRecords();
    
        List<SetmealDto> list = records.stream().map(item -> {
            SetmealDto setmealDto = new SetmealDto();
            // 对象拷贝
            BeanUtils.copyProperties(item, setmealDto);
            // 分类id
            Long categoryId = item.getCategoryId();
            // 根据分类id查询分类对象
            Category category = categoryService.getById(categoryId);
            if (category != null) {
                // 分类名称
                String categoryName = category.getName();
                setmealDto.setCategoryName(categoryName);
            }
            return setmealDto;
        }).collect(Collectors.toList());
    
        dtoPage.setRecords(list);
        return R.success(pageInfo);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    3.2、方法二:联表查询方法

    3.2.1、SetmealController

    /**
     * 套餐信息分页查询
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    public R<Page<SetmealDto>> page(int page, int pageSize, String name) {
        // 分页构造器
        Page<SetmealDto> pageInfo = new Page<>(page, pageSize);
    
        setmealService.querySetmealPageWithCategoryName(pageInfo, name);
    
        return R.success(pageInfo);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.2.2、SetmealService

    // 查询带分类名的套餐分页信息
    void querySetmealPageWithCategoryName(Page<SetmealDto> pageInfo, String name);
    
    • 1
    • 2

    3.2.3、SetmealServiceImpl

    /**
     * 查询带分类名的套餐分页信息
     * @param pageInfo
     * @param name
     */
    @Override
    public void querySetmealPageWithCategoryName(Page<SetmealDto> pageInfo, String name) {
        List<SetmealDto> records = setmealMapper.querySetmealPageWithCategoryName(pageInfo, name == null ? "" : name);
        pageInfo.setRecords(records);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.2.4、SetmealMapper

    @Select("SELECT a.*, b.`name` AS category_name FROM setmeal a JOIN category b ON a.`category_id` = b.`id` WHERE a.`name` LIKE CONCAT('%',#{name},'%') AND a.`is_deleted` = 0 ORDER BY sort")
    List<SetmealDto> querySetmealPageWithCategoryName(Page<SetmealDto> pageInfo, String name);
    
    • 1
    • 2

    3.3、套餐管理页面阿里云OSS图片显示

    修改backend/page/combo/list.html文件以下两处地方

    image-20220619171621422

    image-20220619171653708

    3.4、测试分页查询

    image-20220619173331821

    4、删除套餐信息

    1. 前端发送删除请求,参数形式为ids=id1,id2,...
    2. 后端接收请求,根据id先删除表setmeal_dish表的内容,在删除setmeal表的内容

    删除方法为逻辑删除

    4.1 修改Setmeal和SetmealDish实体类

    修改两个实体类的isDeleted属性,加上@TableLogic(value = "0", delval = "1")注解。用于逻辑删除。标注了此注解后,调用mybatis-plus框架里给的删除方法,会转变成对is_deleted字段的更新方法

    //是否删除
    @TableLogic(value = "0", delval = "1")
    private Integer isDeleted;
    
    • 1
    • 2
    • 3

    4.2、SetmealController

    创建delete方法

    /**
     * 删除套餐
     * @param ids
     * @return
     */
    @DeleteMapping
    public R<String> delete(@RequestParam Long[] ids) {
        log.info("要删除套餐的ids:{}", Arrays.toString(ids));
        
        setmealService.removeSetmealWithDish(ids);
        
        return R.success("套餐数据删除成功");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    4.3、SetmealService

    // 删除套餐,同时需要删除套餐和菜品的关联数据
    void removeSetmealWithDish(Long[] ids);
    
    • 1
    • 2

    4.4、SetmealServiceImpl

    /**
     * 删除套餐,同时需要删除套餐和菜品的关联数据
     * @param ids
     */
    @Override
    @Transactional
    public void removeSetmealWithDish(Long[] ids) {
        // 查询套餐状态,确定是否可用删除
        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Setmeal::getId, ids);
        queryWrapper.eq(Setmeal::getStatus, 1);
        int count = this.count(queryWrapper);
        if (count > 0) {
            // 当前套餐正在出售,不能删除
            throw new CustomException("套餐正在售卖中,不能删除");
        }
    
        // 如果可用删除,先删除表setmeal_dish中关联的菜品信息
        // delete from setmeal_dish where setmeal_id in ()
        LambdaQueryWrapper<SetmealDish> setmealDishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        setmealDishLambdaQueryWrapper.in(SetmealDish::getSetmealId, ids);
        setmealDishService.remove(setmealDishLambdaQueryWrapper);
    
        // 然后删除套餐信息
        this.removeByIds(Arrays.asList(ids));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    4.5、测试删除套餐

    5、修改套餐信息(可选)

    5.1、套餐数据回显

    点击修改后,前端页面会发送一个查询请求,带有id参数

    image-20220619195308895

    我们需要返回一个SetmealDto类型的对象

    5.1.1、SetmealController

    /**
     * 根据id查询套餐信息和对应的菜品信息
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public R<SetmealDto> get(@PathVariable Long id) {
        SetmealDto setmealDto = setmealService.getByIdWithDish(id);
        return R.success(setmealDto);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    5.1.2、SetmealService

    // 根据id查询套餐信息和对应的菜品信息
    SetmealDto getByIdWithDish(Long id);
    
    • 1
    • 2

    5.1.3、SetmealServiceImpl

    /**
     * 根据id查询套餐信息和对应的菜品信息
     * @param id
     * @return
     */
    @Override
    @Transactional
    public SetmealDto getByIdWithDish(Long id) {
        // 查询套餐基本信息
        Setmeal setmeal = this.getById(id);
    
        SetmealDto setmealDto = new SetmealDto();
        BeanUtils.copyProperties(setmeal, setmealDto);
    
        // 查询当前套餐对应的菜品信息
        // select * from setmeal_dish where setmeal_id = id;
        LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SetmealDish::getSetmealId, id);
        List<SetmealDish> setmealDishes = setmealDishService.list(queryWrapper);
    
        setmealDto.setSetmealDishes(setmealDishes);
    
        return setmealDto;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    5.1.4、阿里云OSS图片回显(可选)

    修改backend/page/combo/add.html文件以下内容

    image-20220619200351111

    5.1.5、测试数据回显

    5.2、保存修改信息

    先删除setmeal对应的所有dish,在进行添加

    5.2.1、SetmealController

    /**
     * 修改套餐
     * @param setmealDto
     * @return
     */
    @PutMapping
    public R<String> update(@RequestBody SetmealDto setmealDto) {
        log.info("保存修改套餐信息:{}", setmealDto);
        setmealService.updateSetmealWithDish(setmealDto);
        return R.success("修改套餐成功");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    5.2.2、SetmealService

    // 更新套餐信息
    void updateSetmealWithDish(SetmealDto setmealDto);
    
    • 1
    • 2

    5.2.3、SetmealServiceImpl

    /**
     * 更新套餐信息
     * @param setmealDto
     */
    @Override
    public void updateSetmealWithDish(SetmealDto setmealDto) {
        // 更新setmeal表基本信息
        this.updateById(setmealDto);
    
        // 删除原来对应的菜品信息
        LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SetmealDish::getSetmealId, setmealDto.getId());
        setmealDishService.remove(queryWrapper);
    
        // 添加新的菜品信息
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        setmealDishes = setmealDishes.stream().peek(item -> item.setSetmealId(setmealDto.getId())).collect(Collectors.toList());
        setmealDishService.saveBatch(setmealDishes);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    5.2.4、测试修改套餐

    6、批量起售/停售套餐(可选)

    前端页面请求:

    image-20220619215306929

    6.1、SetmealController

    /**
     * 批量起售/停售套餐
     * @param status
     * @param ids
     * @return
     */
    @PostMapping("/status/{status}")
    public R<String> status(@PathVariable("status") int status, @RequestParam Long[] ids) {
        log.info("批量起售停售:{}", status, Arrays.toString(ids));
        setmealService.updateStatusByIds(status, ids);
        return R.success("批量起售停售成功");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    6.2、SetmealService

    // 批量起售停售套餐
    void updateStatusByIds(int status, Long[] ids);
    
    • 1
    • 2

    6.3、SetmealServiceImpl

    不知道为什么mybat-plus没有提供批量修改的方法。

    这里我为了方便就直接在循环里更新了。

    还有一种方法是在mapper文件里进行批量更新。

    不知道哪种方法更优雅一点。如果有大佬知道希望能在评论区解答一下。

    /**
     * 批量起售停售套餐
     * @param status
     * @param ids
     */
    @Override
    public void updateStatusByIds(int status, Long[] ids) {
        // 查询出所有对应id的setmeal
        List<Setmeal> setmeals = setmealMapper.selectBatchIds(Arrays.asList(ids));
    
        // 循环遍历更新
        setmeals.forEach(item -> {
            item.setStatus(status);
            setmealMapper.updateById(item);
        });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    6.4、测试批量起售停售

  • 相关阅读:
    基于语雀编辑器的在线文档编辑与查看
    RK3568平台开发系列讲解(AI篇)车辆检测&车道线识别&可行驶区域分割 模型对比检测结果
    java代码审计(入门级)—基础漏洞合集
    机器学习基础知识
    Flutter笔记:关于Flutter中的大文件上传(上)
    数据结构-双链表思路解析及代码实现
    反射的概念 和基本使用(一)
    入门级 Python变量类型和运算符知识点整理
    界面控件DevExpress WPF TreeMap,轻松可视化复杂的分层结构数据!
    好心情精神心理科医生:抗抑郁药物是否成瘾?
  • 原文地址:https://blog.csdn.net/xjhqre/article/details/125412854