基于Springboot外卖系统20:前端菜品展示+菜品数量查询

1 菜品展示

1.1 需求分析

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

 

1.2 前端页面分析

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

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

该功能已经实现了。通过请求响应的数据可以看到数据是可以正确获取到的。

左侧的分类菜单,和右侧的菜品信息都可以看到,后续只需要将购物车列表的数据改成调用服务端接口查询即可。

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

 A. 根据分类ID查询套餐列表:

 B. 根据分类ID查询菜品列表:

 异步请求,查询分类对应的菜品列表已经实现了,但是查询的只是菜品的基本信息,不包含菜品的口味信息。所以在前端界面中看不到选择菜品分类的信息。

经过上述的分析,服务端我们主要提供两个方法, 分别用来:

A. 根据分类ID查询菜品列表(包含菜品口味列表), 具体请求信息如下:

请求说明
请求方式GET
请求路径/dish/list
请求参数?categoryId=1397844263642378242&status=1

该功能在服务端已经实现,需要修改此方法,在原有方法的基础上增加查询菜品的口味信息。

B. 根据分类ID查询套餐列表, 具体请求信息如下:

请求说明
请求方式GET
请求路径/setmeal/list
请求参数?categoryId=1397844263642378242&status=1

该功能在服务端并未实现。

2 代码开发

2.1 查询菜品方法修改

由于之前实现的根据分类查询菜品列表,仅仅查询了菜品的基本信息,未查询菜品口味信息,而移动端用户在点餐时,是需要选择口味信息的,所以需要对之前的代码实现进行完善。

需要修改DishController的list方法,原来此方法的返回值类型为:R<List<Dish>>。为了满足移动端对数据的要求(菜品基本信息和菜品对应的口味信息),现在需要将方法的返回值类型改为:R<List<DishDto>> ,因为在DishDto中封装了菜品对应的口味信息:

代码逻辑:

A. 根据分类ID查询,查询目前正在启售的菜品列表 (已实现)

B. 遍历菜品列表,并查询菜品的分类信息及菜品的口味列表

C. 组装数据DishDto,并返回

1 DishController中增加根据条件查询对应的菜品数的list()方法

package com.itheima.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;
import java.util.stream.Collectors;/*** Description: 菜品管理 菜品及菜品口味的相关操作,统一使用这一个controller即可。* @version 1.0* @date 2022/8/18 11:08*/@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {@Autowiredprivate DishService dishService;@Autowiredprivate DishFlavorService dishFlavorService;@Autowiredprivate CategoryService categoryService;@PostMappingpublic R<String> save(@RequestBody DishDto dishDto){/**@Description: 新增菜品* @author LiBiGo* @date 2022/8/18 11:44*/log.info(dishDto.toString());dishService.saveWithFlavor(dishDto);return R.success("新增菜品成功");}@GetMapping("/page")public R<Page> page(int page,int pageSize,String name){/**@Description: 菜品信息分页查询* @author LiBiGo** 数据库查询菜品信息时,获取到的分页查询结果 Page 的泛型为 Dish,而最终需要给前端页面返回的类型为DishDto,* 所以这个时候就要进行转换,基本属性直接通过属性拷贝的形式对Page中的属性进行复制,* 对于结果列表 records属性需要进行特殊处理的(需要封装菜品分类名称);** @date 2022/8/19 10:41*/// 构造分页构造器对象Page<Dish> pageInfo = new Page<>(page,pageSize);Page<DishDto> dishDtoPage = new Page<>();// 条件构造器LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();// 添加过滤条件queryWrapper.like(name!=null,Dish::getName,name);// 添加排序条件queryWrapper.orderByDesc(Dish::getUpdateTime);// 执行分页查询dishService.page(pageInfo,queryWrapper);// 对象的拷贝BeanUtils.copyProperties(pageInfo,dishDtoPage,"records");List<Dish> records = pageInfo.getRecords();List<DishDto> list = records.stream().map((item) -> {DishDto dishDto = new DishDto();BeanUtils.copyProperties(item,dishDto);Long categoryId = item.getCategoryId();//分类id//根据id查询分类对象Category category = categoryService.getById(categoryId);if(category != null){String categoryName = category.getName();dishDto.setCategoryName(categoryName);}return dishDto;}).collect(Collectors.toList());dishDtoPage.setRecords(list);return R.success(dishDtoPage);}@GetMapping("/{id}")public R<DishDto> get(@PathVariable Long id){/**@Description: 根据id查询菜品信息和对应的口味信息* @author LiBiGo* @date 2022/8/19 11:43*/DishDto dishDto = dishService.getByIdWithFlavor(id);return R.success(dishDto);}@PutMapping// @PathVariable : 该注解可以用来提取url路径中传递的请求参数。public R<String> update(@RequestBody DishDto dishDto){/**@Description: 修改菜品* @author LiBiGo* @date 2022/8/19 11:58*/log.info(dishDto.toString());dishService.updateWithFlavor(dishDto);return R.success("新增菜品成功");}//    @GetMapping("/list")
//    public R<List<Dish>> list(Dish dish){
//        /**@Description: 根据条件查询对应的菜品数
//         * @author LiBiGo
//         * @date 2022/8/19 15:49
//         */
//        // 构造查询条件
//        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());
//        //添加条件,查询状态为1(起售状态)的菜品
//        queryWrapper.eq(Dish::getStatus,1);
//
//        //  添加排序条件
//        queryWrapper.orderByDesc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
//
//        List<Dish> list = dishService.list(queryWrapper);
//
//        return R.success(list);
//    }@GetMapping("/list")public R<List<DishDto>> list(Dish dish){/**@Description: 根据条件查询对应的菜品数* @author LiBiGo* @date 2022/8/19 15:49*/// 构造查询条件LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());//添加条件,查询状态为1(起售状态)的菜品queryWrapper.eq(Dish::getStatus,1);//  添加排序条件queryWrapper.orderByDesc(Dish::getSort).orderByDesc(Dish::getUpdateTime);List<Dish> list = dishService.list(queryWrapper);List<DishDto> dishDtoList = list.stream().map((item) -> {DishDto dishDto = new DishDto();BeanUtils.copyProperties(item,dishDto);Long categoryId = item.getCategoryId();//分类id//根据id查询分类对象Category category = categoryService.getById(categoryId);if(category != null){String categoryName = category.getName();dishDto.setCategoryName(categoryName);}//当前菜品的idLong dishId = item.getId();LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(DishFlavor::getDishId,dishId);//SQL:select * from dish_flavor where dish_id = ?List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);dishDto.setFlavors(dishFlavorList);return dishDto;}).collect(Collectors.toList());return R.success(dishDtoList);}}

2 在SetmealController中创建list()方法,根据条件查询套餐数据。

package com.itheima.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.SetmealDto;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Setmeal;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.SetmealDishService;
import com.itheima.reggie.service.SetmealService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;
import java.util.stream.Collectors;
/*** Description: 套餐管理* 不仅需要保存套餐的基本信息,还需要保存套餐关联的菜品数据,所以需要再该方法中调用业务层方法,完成两块数据的保存。* @version 1.0* @date 2022/8/19 15:37*/@RestController
@RequestMapping("/setmeal")
@Slf4j
public class SetmealController {@Autowiredprivate SetmealService setmealService;@Autowiredprivate CategoryService categoryService;@Autowiredprivate SetmealDishService setmealDishService;@PostMapping// 页面传递的数据是json格式,需要在方法形参前面加上@RequestBody注解, 完成参数封装。public R<String> save(@RequestBody SetmealDto setmealDto){/**@Description: 新增套餐* @version v1.0* @author LiBiGo* @date 2022/8/19 16:04*/log.info("套餐信息:{}",setmealDto);setmealService.saveWithDish(setmealDto);return R.success("新增套餐成功");}@GetMapping("/page")public R<Page> page(int page,int pageSize,String name){/**@Description: 套餐分页查询* @author LiBiGo* @date 2022/8/21 10:40*/// 分页构造器对象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,"record");List<Setmeal> records = pageInfo.getRecords();List<SetmealDto> list = records.stream().map((item) -> {SetmealDto setmealDto = new SetmealDto();//对象拷贝BeanUtils.copyProperties(item,setmealDto);//分类idLong 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(dtoPage);}@DeleteMappingpublic R<String> delete(@RequestParam List<Long> ids){/**@Description: 删除套餐* @author LiBiGo* @date 2022/8/21 11:35*/log.info("ids:{}",ids);setmealService.removeWithDish(ids);return R.success("套餐数据删除成功");}@GetMapping("/list")public R<List<Setmeal>> list(Setmeal setmeal) {/*** 根据条件查询套餐数据* @param setmeal* @return*/log.info("setmeal:{}", setmeal);//条件构造器LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.like(StringUtils.isNotEmpty(setmeal.getName()), Setmeal::getName, setmeal.getName());queryWrapper.eq(null != setmeal.getCategoryId(), Setmeal::getCategoryId, setmeal.getCategoryId());queryWrapper.eq(null != setmeal.getStatus(), Setmeal::getStatus, setmeal.getStatus());queryWrapper.orderByDesc(Setmeal::getUpdateTime);return R.success(setmealService.list(queryWrapper));}}

3 功能测试

测试过程中可以使用浏览器的监控工具查看页面和服务端的数据交互细节。

 点击分类,根据分类查询菜品列表/套餐列表:

 

 

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

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

相关文章

flash动画设计期末作业_「2019年下学期」第二十五二十六节:期末作品三-吉祥物设计...

初心伟大的艺术品不必追随潮流&#xff0c;他本身就能引领潮流。课前准备软件安装【2019(上)】《三维建模与动画设计》【2019年下学期】第一节&#xff1a;选修介绍及选修人数确定【2019年下学期】第二节&#xff1a;2D&3D设计之百事可乐图标设计【2019年下学期】第三四节&…

YOLOv7: Trainable bag-of-freebies sets new state-of-the-art for real-time object detectors

来源&#xff1a;https://arxiv.org/abs/2207.02696 代码&#xff1a;https://github.com/WongKinYiu/yolov7 0. Abstract YOLOv7 surpasses all known object detectors in both speed and accuracy in the range from 5 FPS to 160 FPS and has the highest accuracy 56.8…

如何把一个网页生成一个快捷方式在桌面?_如何打造一个简洁、高效的桌面?

都2020年了&#xff0c;你的桌面仍是这样的&#xff1f; 或是这样的&#xff1f; 但当然你也见过这样的&#xff1a; 你当然会好奇&#xff0c;没有各种快捷方式、任何文件或文件夹的工作桌面&#xff0c;使用起来岂不效率低下&#xff1f;然则非也。我认为高效的工作得从舒服的…

Android ADB 源码分析(三)

前言 之前分析的两篇文章 Android Adb 源码分析(一) 嵌入式Linux&#xff1a;Android root破解原理&#xff08;二&#xff09; 写完之后&#xff0c;都没有写到相关的实现代码&#xff0c;这篇文章写下ADB的通信流程的一些细节 看这篇文章之前&#xff0c;请先阅读 Linux…

A Generative Adversarial Network-based Deep Learning Method for Low-quality Defect ImageReconstructi

A Generative Adversarial Network-based Deep Learning Method for Low-quality Defect ImageReconstruction and Recognition 中文名&#xff1a;基于生成对抗网络的深度低质量缺陷图像的学习方法重建与认可 主体思路概述&#xff1a;将模糊的图像使用Gan进行生成与重建&…

bootstrap3 表单构建器_FastReport.NET报表设计器连接到OracleDB关系数据库

首先&#xff0c;您可以使用ODBC连接器。但是它充满了很多设置。FastReport.NET报表设计器连接到OracleDB关系数据库如您所见&#xff0c;您需要创建数据源及其连接字符串。动作比较多。此方法的替代方法是使用FastReport中的连接器。实际上&#xff0c;有两个连接器可供选择。…

码农,选好你的老板

[01 两个小故事] 小明2009年毕业 那一年刚好是金融危机之后&#xff0c;全球经济还不是很好&#xff0c;找到一份好的工作非常困难。 好在&#xff0c;小明误打误撞面试上华为一份码农的工作。 刚开始那几年&#xff0c;小明很拼命&#xff0c;不断的在解bug和制造bug中自由…

Automated defect inspection system for metal surfaces based on deep learning and data augmentation

Automated defect inspection system for metal surfaces based on deep learning and data augmentation 基于深度学习和数据增强的金属表面缺陷自动检测系统 简述&#xff1a;卷积变分自动编码器(CVAE)生成特定的图像&#xff0c;再使用基于深度CNN的缺陷分类算法进行分类。在…

python第七章_python 第七章 模块

模块 一个py文件就是一个模块 模块一共三种&#xff1a;1.python标准库 2.第三方模块 3.应用程序自定义模块 import&#xff1a;1.执行对应文件 2.引入变量名 if__name__"__main__": #1.用于被调用文件测试 2.防止主程序被调用 time模块 常用命令 时间模块 1 importt…

openwrt 音频开发

1、Linux 音频架构图 音视频的好坏 直接影响 产品体验 2、音频架构图层次说明 openWRT 采用 ALSA 层次图,如下 Application: 上层应用 主要调用alsa-lib 中的接口 实现业务逻辑。使用alsa-util中aplay,arecord,amixer,speaker-test进行相关测试。HAL层 : 移植alsa-lib 和 a…

Automatic Detection of Welding Defects Using Faster R-CNN

Automatic Detection of Welding Defects Using Faster R-CNN 基于快速R-CNN的焊接缺陷自动检测 简介&#xff1a;使用Inception-ResNet模型进行缺陷检测 数据集&#xff1a;射线图像 Abstract Experts are required to properly detect the test results and it takes a lot…

让Android Studio支持系统签名(证书)

有时候&#xff0c;我们开发的apk需要用到系统权限&#xff0c;需要在AndroidManifest.xml中添加共享系统进程属性&#xff1a; android:sharedUserId"android.uid.system" android:sharedUserId"android.uid.shared" android:sharedUserId"android…

eslint 保存自动格式化_代码规范之理解ESLint、Prettier、EditorConfig

授权转载自&#xff1a;nowThenhttps://juejin.cn/post/6895889063111294990前言团队多人协同开发项目中困恼团队管理一个很大的问题是&#xff1a;无可避免地会出现每个开发者编码习惯不同、代码风格迥异&#xff0c;为了代码高可用、可维护性&#xff0c; 如何从项目管理上尽…

Deep learning based multi-scale channel compression feature surface defect detection system

基于深度学习的多尺度通道压缩特征表面缺陷检测系统 Deep learning based multi-scale channel compression feature surface defect detection system 简述&#xff1a;首先应用背景分割和模板匹配技术来定义覆盖目标工件的ROI区域。提取的感兴趣区域被均匀地裁剪成若干个图像…

前端MVC框架之 Angular

一、什么是Angular jQuery&#xff0c;它属于一种类库(一系列函数的集合)&#xff0c;以DOM为驱动核心&#xff1b;而Angular是一种 MVC 的前端框架&#xff0c;则是前端框架&#xff0c;以数据和逻辑为驱动核心&#xff0c;它有着诸多特性&#xff0c;最重要的是&#xff1a;模…

C语言关键字(三)

之前的两篇文章 嵌入式Linux&#xff1a;c语言深度解剖&#xff08;数据类型关键字&#xff09;​zhuanlan.zhihu.com 嵌入式Linux&#xff1a;c语言深度解剖&#xff08;入门篇&#xff09;​zhuanlan.zhihu.com 这篇文件继续讲解C语言关键字 想问大家一个问题&#xff0c…

python bottle框架 运维_python bottle 框架实战教程:任务管理系统 V_1.0版 | linux系统运维...

经过1-2个星期的开发&#xff0c;现在用任务管理功能&#xff08;添加、删除、修改&#xff0c;详细&#xff09;、项目管理功能&#xff08;添加、删除&#xff0c;修改&#xff0c;详细&#xff09;等&#xff0c;我把现在完成的版本&#xff0c;叫做1.0吧。发布完这个版本后…

form 窗体增加边框_C#控件美化之路(13):美化Form窗口(上)

在开发中最重要的就是美化form窗口&#xff0c;在开发中&#xff0c;大多都是用会用自主美化的窗口开发程序。本文只是点多&#xff0c;分为上中下节。分段讲解。本文主要讲解窗口美化关键步骤。首先美化窗体&#xff0c;就需要自己绘制最大化 最小化 关闭按钮。其次就是界面样…

第四周数据结构

转载于:https://www.cnblogs.com/bgd150809329/p/6650255.html

gdb x命令_gdb基本命令

参考自&#xff1a;gdb基本命令(非常详细)_JIWilliams-CSDN博客_gdb命令​blog.csdn.net本文介绍使用gdb调试程序的常用命令。 GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。如果你是在 UNIX平台下做软件&#xff0c;你会发现GDB这个调试工具有比VC、BCB的图形化调试…