外卖项目05---套餐管理业务开发

套餐:一组菜品的集合

点击之后就会弹出下面的界面:

上面是后台的管理操作,下面是处理完成后在用户端展示的界面效果:

目录

一、新增套餐 70

1.1需求分析 70

1.2数据模型 70

1.3新增套餐---代码开发---准备工作&梳理交互过程 71

1.3.1代码准备工作(类的导入,服务层的编写)71

1.4新增套餐---代码开发---根据分类查询菜品 72

1.5新增套餐---代码开发---服务端接收页面提交的数据 73

1.6新增套餐---代码开发---保存数据到对应表 74

1.7新增套餐---功能测试 75

二、套餐信息分页查询 76

2.1需求分析 76

2.2代码开发---梳理交互过程 76

2.3套餐信息分页查询---代码开发&功能测试 77

三、删除套餐 (关联表之间的删除)78

3.1需求分析 78

3.2代码开发---梳理交互过程 78

3.3删除套餐---代码开发&功能测试 79

四、手机验证码登陆 80

五、短信发送 81

5.1短信服务介绍和阿里云短信服务介绍 81

5.2短信发送---阿里云短信服务 82 

5.2.1阿里云短信服务---注册账号 82

5.3短信发送---代码开发---参照官方文档封装短信发送工具类 83

六、手机验证码登陆 84 

6.1需求分析 84

6.2数据模型 84 

6.3手机验证码登陆---代码开发---梳理交互过程&修改LoginCheckFliter 85

6.3.1代码开发---梳理交互过程 85

6.3.2代码开发---准备工作 85

6.4手机验证码登陆---代码开发 86

6.5手机验证码登陆---代码开发---登陆校验 86


一、新增套餐 70

1.1需求分析 70

1.2数据模型 70

 

1.3新增套餐---代码开发---准备工作&梳理交互过程 71

1.3.1代码准备工作(类的导入,服务层的编写)71

1.4新增套餐---代码开发---根据分类查询菜品 72

1.3.1中的交互过程包含六次交互请求,前两次的请求交互在CategoryController中进行。

选用其中的List集合中的数据信息。

这两种类都在List中进行。

实现的是下面的效果内容:

 本部分代码实现的效果: 

本部分使用的代码如下所示:

    /*** 根据条件查询对应的菜品数据* @param dish* @return*/@GetMapping("/list")public R<List<Dish>> list(Dish dish){//这个部分传递的参数,可以是Long categoryid,// 但是可以将其进行扩展使用,使用Dish类中的参数,它包含了很多的参数信息,包含categoryid//构造查询条件LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(dish.getCategoryId() != null , Dish::getCategoryId,dish.getCategoryId());//该部分是设置一个判断语句,确定id传递过来,并不是空的指针//添加排序条件queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);//使用了两个判断条件,一个是根据sort进行升序排序,如果sort排序一致,再根据更新时间进行降序判断//添加条件,查询状态为1(起售状态)的菜品queryWrapper.eq(Dish::getStatus,1);List<Dish> list = dishService.list(queryWrapper);//使用该方法,获取得到了一个集合return R.success(list);}

1.5新增套餐---代码开发---服务端接收页面提交的数据 73

下面部分代码开发实现的内容: 

 使用的是CommonController层的图片上传和下载的功能。

下面本部分实现的是下面的效果:

将客户端的数据信息发布反馈到后端当中:

反馈到后端的内容数据信息: 

本部分代码:

    /*** 新增套餐* @param setmealDto* @return*/@PostMappingpublic R<String> save(@RequestBody SetmealDto setmealDto){log.info("套餐信息: {}",setmealDto);return  null;}

1.6新增套餐---代码开发---保存数据到对应表 74

套餐表中插入数据、套餐和菜品对应的关系表里面进行插入数据处理。这两个表都需要进行处理。

对两张表的操作。

在SetmealService接口中进行处理。

本部分的代码如下所示:底层对两个表之间处理。

步骤一:对SetmealService接口进行修改

代码:

    /*** 新增套餐* @param setmealDto* @return*/@PostMappingpublic R<String> save(@RequestBody SetmealDto setmealDto){log.info("套餐信息: {}",setmealDto);return  R.success("新增套餐成功");}

步骤二:在SetmealServiceImpl驱动类中进行修改。

    /*** 新增套餐,同时需要保存套餐和菜品的关联关系* @param setmealDto*/@Transactionalpublic void saveWithDish(SetmealDto setmealDto) {//保存套餐的基本信息,操作setmeal,执行insert操作this.save(setmealDto);List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();setmealDishes.stream().map((item) -> {item.setSetmealId(setmealDto.getId());return item;}).collect(Collectors.toList());//保存套餐和菜品的关联信息,操作setmeal_dish,执行insert操作setmealDishService.saveBatch(setmealDishes);}

1.7新增套餐---功能测试 75

二、套餐信息分页查询 76

2.1需求分析 76

2.2代码开发---梳理交互过程 76

一共能涉及到2次请求信息 

 注:

1、中的name参数获取

 2、图片进行展示

2.3套餐信息分页查询---代码开发&功能测试 77

        目前下面的代码能够实现主要的内容,但是在套餐分类的这一类当中是不进行显示的。是由于pageInfo中继承的泛型是Setmeal。

 但是Setmeal中不包含套餐分类的功能,只是返回的是套餐分类的id。

本部分解决套餐分类中分类的类别显示问题:

问题描述如下:

本部分代码:

    /*** 套餐分页查询* @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<>();//使用SetmealDto中的内容对象,进行使用操作处理,// 由于SetmealDto继承Setmeal,并且还包含那个套餐分类的名称,所以使用该类LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();//添加查询条件,根据name进行like模糊查询queryWrapper.like(name != null,Setmeal::getName,name);//括号内是进行条件的查询的判断,判断内容不为空,// 并且进行name模糊查询//添加排序条件,根据更新时间降序排序queryWrapper.orderByDesc(Setmeal::getUpdateTime);setmealService.page(pageInfo,queryWrapper);//对象拷贝BeanUtils.copyProperties(pageInfo,dtoPage,"records");//是将pageInfo中的数据拷贝到dtoPage中//并且忽略pageInfo中的records的保存数据的信息记录。由于pageInfo中的泛型为Setmeal,//我们新创建的是dtoPage的泛型为SetmealDto,所以需要进行先排除List<Setmeal> records = pageInfo.getRecords();//获取pageInfo中的records,对后面的这个records进行处理解决List<SetmealDto> list =  records.stream().map((item) ->{SetmealDto setmealDto = new SetmealDto();//对象拷贝,因为创建的集合SetmealDto中是空的,所以需要将原来item的数据内容拷贝到新的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);//将查询到的categoryName添加到setmealDto中//因为创建的setmealDto是个新的集合,所以使用set进行添加到集合中}return setmealDto;}).collect(Collectors.toList());dtoPage.setRecords(list);return R.success(dtoPage);}

三、删除套餐 (关联表之间的删除)78

3.1需求分析 78

需求:

1、点击删除按钮删除商品

2、批量删除商品的实现

3、停售按键的正常使用,售卖的套餐不能被删除,停售后才能够被删除 

3.2代码开发---梳理交互过程 78

 注:

1、请求方式和请求地址是相同的

2、区别在于两者的传递的id的个数不一样

3.3删除套餐---代码开发&功能测试 79

步骤一:在SetmealController层中进行书写删除的主代码

    /*** 删除套餐* @param ids* @return*/@DeleteMappingpublic R<String> delete(@RequestParam List<Long> ids){log.info("ids:{}",ids);
//        setmealService.removeWithDish(ids);return R.success("套餐删除成功");}

步骤二:在SetmealSerice接口中创建新的方法

    public void removeWithDish(List<Long> list);

步骤三:添加服务驱动类

    /*** 删除套餐,同时需要删除套餐和菜品的关联数据* @param ids*/@Overridepublic void removeWithDish(List<Long> ids) {//select count(*) from setmeal where id in (1,2,3) and status =1//查询套餐状态,确定是否可用删除LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.in(Setmeal::getId,ids);//是查询判断的第一部分条件是在(1,2,3)中进行查询进行表达queryWrapper.eq(Setmeal::getStatus,1);//判断条件等值查询判断,判断该商品的状态,1:在售;2:停售int count = this.count(queryWrapper);//ServiceImpl实现的框架下的一个count,封装生成if(count > 0 ){//异常提示报错,>0表示状态为1,处于售卖的状态。//如果不能被删除,抛出一个业务异常throw new CustomException("套餐正在售卖中,不能删除");}//如果可以删除,先删除套餐表中的数据---setmeal  这个是套餐(批量删除)this.removeByIds(ids);//删除关系表中的数据---setmeal_dish(关联数据)//创建一个新的处理方式,mysql中的编程处理的代码 delete from setmeal_dish where setmeal_id in (1,2,3...)LambdaQueryWrapper<SetmealDish> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.in(SetmealDish::getSetmealId,ids);//该部分表示mysql的代码编写//删除关系表中的数据---setmeal_dishsetmealDishService.remove(lambdaQueryWrapper);}

步骤四:在主方法中进行调用使用该方法

    /*** 删除套餐* @param ids* @return*/@DeleteMappingpublic R<String> delete(@RequestParam List<Long> ids){log.info("ids:{}",ids);setmealService.removeWithDish(ids);return R.success("套餐删除成功");}

四、手机验证码登陆 80

五、短信发送 81

5.1短信服务介绍和阿里云短信服务介绍 81

5.2短信发送---阿里云短信服务 82 

5.2.1阿里云短信服务---注册账号 82

 

 

5.3短信发送---代码开发---参照官方文档封装短信发送工具类 83

六、手机验证码登陆 84 

6.1需求分析 84

6.2数据模型 84 

6.3手机验证码登陆---代码开发---梳理交互过程&修改LoginCheckFliter 85

6.3.1代码开发---梳理交互过程 85

6.3.2代码开发---准备工作 85

 修改部分一:

修改部分二:

6.4手机验证码登陆---代码开发 86

 本部分代码如下:

代码:

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;public R<String> sendMsg(@RequestBody User user, HttpSession session){//获取手机号String phone = user.getPhone();if (StringUtils.isNotEmpty(phone)){//首先进行条件判断//生成4位随机的验证码,通过ailiyun提供的功能类String code = ValidateCodeUtils.generateValidateCode(4).toString();log.info("code={}",code);//调用阿里云提供的短信服务API完成发送短信
//            SMSUtils.sendMessage("瑞吉外卖","",phone,code);//需要将生成的验证码保存到Sessionsession.setAttribute(phone,code);return R.success("手机验证码短信发送成功");}return R.error("短信发送失败");}}

6.5手机验证码登陆---代码开发---登陆校验 86

使得前端能够进行登陆

本部分代码:

    /*** 移动端用户登陆* @param map* @param session* @return*/@PostMapping("/login")public R<User> login(@RequestBody Map map, HttpSession session){//使用Map类log.info(map.toString());//获取手机号String phone = map.get("phone").toString();//获取验证码String code = map.get("code").toString();//从Session中获取保存的验证码Object codeInSession = session.getAttribute(phone);//进行验证码的比对(页面提交的验证码和Session中保存的验证码比对)if(codeInSession != null && codeInSession.equals(code)){//如果能够对比成功,说明登陆成功LambdaQueryWrapper<User> queryWrapper =new LambdaQueryWrapper<>();queryWrapper.eq(User::getPhone,phone);User user = userService.getOne(queryWrapper);if(user == null){//判断当前手机号对应的用户是否位新用户,如果是新用户就自动完成注册user = new User();user.setPhone(phone);user.setStatus(1);userService.save(user);}return R.success(user);}return R.error("登陆失败");}

效果:实现在移动端进行登陆

注:如果登陆时出现登陆不上的情况,可以尝试清理下浏览器的缓存,在进行登陆。

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

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

相关文章

校园外卖点餐系统——Day04【菜品管理业务开发】

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

小饭馆拓客营销流程,小饭馆宣传推广方案

基于目前持续回暖的餐饮行业&#xff0c;小饭馆起死回生&#xff0c;业绩翻倍&#xff0c;关键在于营销推广。那么如何进行小饭馆的推广&#xff1f;今天我们就和各位聊聊小饭馆引流推广应该如何做&#xff01; 小饭馆营销推广流程 小饭馆引流推广方案主要包含如下&#xff1a…

基于python Django 餐馆点菜管理系统

问题描述&#xff1a; 随着网络的迅速发展&#xff0c;越来越多的人开始接受甚至时依赖了网络营业的这种交易形式&#xff0c;传统的点菜模式不仅浪费时间&#xff0c;效率低下&#xff0c;而且特别耗费成本与人力&#xff0c;因此不少商家开始使用网上点菜系统。网上点菜系统是…

软件测试项目实战,一比一还原可以写进简历的

项目一&#xff1a;ShopNC商城 项目概况&#xff1a; ShopNC商城是一个电子商务B2C电商平台系统&#xff0c;功能强大&#xff0c;安全便捷。适合企业及个人快速构建个性化网上商城。 包含PCIOS客户端Adroid客户端微商城&#xff0c;系统PC后台是基于ThinkPHP MVC构架开发的跨…

软件测试【个人简历】展示模板

个人简历 就职目标&#xff1a;软件测试工程师 简历是我们求职的第一步&#xff0c;也是非常重要的一步。 如果你简历写的一塌糊涂&#xff0c;那么你瞬间就会被淘汰&#xff0c;那么一份好的简历应该怎么写呢&#xff1f; 一般分为如下几部分内容&#xff1a; 1、个人基本…

软件测试电商项目实战(写进简历没问题)

前言 说实话&#xff0c;在找项目的过程中&#xff0c;我下载过&#xff08;甚至付费下载过&#xff09;N多个项目、联系过很多项目的作者&#xff0c;但是绝大部分项目&#xff0c;在我看来&#xff0c;并不适合你拿来练习&#xff0c;它们或多或少都存在着“问题”&#xff…

如何介绍简历中的项目呢?请看软件测试老师的分享

项目经验与工作经验是相辅相成的&#xff0c;但较之于工作经验&#xff0c;项目经验更侧重于表现求职者在某个专业领域内的技能水平&#xff08;技能水平决定了工资水平&#xff09;。因而&#xff0c;技术类岗招聘的时候&#xff0c;更注重项目经验。项目介绍是有套路的&#…

软件测试的简历里面,项目介绍要怎么写好呢

一、如果你是做功能测试&#xff08;项目介绍可以这样&#xff09; 项目一&#xff1a;2019/4-至今 项目简介&#xff1a;该项目是题库/考勤APP&#xff0c;主要的功能有题库、考勤、用户信息系统、直播视频、社区板块。迭代了多少次xxx,目前正在正常运营xxx. 负责模块&#…

详解9个写进简历的数据分析项目

核心知识点覆盖 Excel、Python、SQL、Pandas、Numpy、Matplotlib、Power BI、PyEcharts可视化、数据指标、波士顿矩阵、数据建模、AARRR模型、漏斗模型、RFM模型、A\BTest、逻辑回归、线性回归、预测分析、K近邻算法、网络爬虫、数据化运营、用户画像体系构建 9大企业项目实战 …

可以写进简历的软件测试项目实战经验(包含电商、银行、app等)

目录 目录 前言&#xff1a; 1、项目名称: 家电购 2、项目名称: 瑞德商城 3、项目名称:随意读(APP) 4、项目&#xff1a;东海农村商行 总结 前言&#xff1a; 今天给大家带来几个软件测试项目的实战总结及经验&#xff0c;适合想自学、转行或者面试的朋友&#xff0c;可…

postmessage通信

在业务中&#xff0c;有一种开发形式为&#xff1a;多个子系统集成为一个父系统。每个系统之间都管理着不同的业务与逻辑&#xff0c;他们是互不干涉的。 那么&#xff0c;我们如何在父系统页面中操作子系统中的内容呢&#xff1f; 首先通过vite初始化两个项目。 父系统端口…

微软历史上的12个Windows操作系统版本排名

作为全球最流行的操作系统之一&#xff0c;Windows 操作系统的发布对世界产生了深远的影响。Windows 操作系统的发布历程可以追溯到 1985 年&#xff0c;当时微软推出了第一个版本的 Windows。随着时间的推移&#xff0c;Windows 不断升级和改进&#xff0c;推出了多个版本&…

独立开发变现周刊(第86期):月收入4000美元的日程规划器

分享独立开发、产品变现相关内容&#xff0c;每周五发布。 目录 1、NotionReads: 在Notion中管理你的阅读书籍2、Zaap.ai: 面向创作者的一站式工具3、microfeed: 开源的可自我托管的轻量级内容管理系统(CMS)4、Reactive Resume&#xff1a;一个免费的开源简历生成器5、一个月收…

苹果的 Vision Pro 会重蹈谷歌眼镜的覆辙吗?

本文作者认为&#xff0c;一款成功的AR头戴式设备需要考虑以下几方面&#xff1a;成本高&#xff0c;回报低&#xff1b;安全与隐私问题&#xff1b;时机与市场&#xff1b;4、设计与社会接受度。 原文链接&#xff1a;https://uxdesign.cc/can-apples-vision-pro-succeed-wher…

chatgpt赋能python:Python描述性统计分析:基础概念、应用和实例分析

Python描述性统计分析&#xff1a;基础概念、应用和实例分析 作为一种高效、可扩展和易于学习的编程语言&#xff0c;Python在文本处理、数据挖掘、机器学习、数据可视化等方面已经得到了广泛应用。在数据分析领域&#xff0c;Python拥有强大的描述性统计分析库&#xff0c;可…

AIGC:Google Bard VS ChatGPT 简介及对比分析

文章目录 [toc]前言一、Bard和ChatGPT二、应用场景三、时效性小结其他 前言 自从 OpenAI 向公众发布ChatGPT以来的过去几个月里&#xff0c;我们都见证了围绕 ChatGPT 的各种测评&#xff0c;并为它带来的效果感到惊艳。昨晚Google开放了自家研发的AI聊天机器人Bard的测评入口…

R语言利用wordcloud2绘制词云

本次的重点绘制词云&#xff0c;所以并不太重视其他分析方面的论述。 本机环境&#xff1a; window 10 R x64 3.3.0 R包&#xff1a; tmcn&#xff1a;词频统计 wordcloud2&#xff1a;绘制词云 Rwordseg&#xff1a;分词 由于tmcn和Rwordseg包在R3.3.0的版本中没有可以…

同一界面画出多个QQ图(R语言)

题目&#xff1a;一名研究者用光子吸收法测量了妇女骨骼中无机物含量&#xff0c;对三根骨头主侧和非主侧记录了测量值&#xff0c;数据框“T1bones.txt”中的第2至第7列记录了相应数据。对各个变量做qq图&#xff0c;在同一个界面画出所有的qq图&#xff0c;不同的qq图用不同颜…

R语言各个包里面的数据集

关注微信公共号&#xff1a;小程在线 关注CSDN博客&#xff1a;程志伟的博客 Package Item Title csv docdatasetsAirPassengersMonthly Airline Passenger Numbers 1949-1960CSVDOCdatasetsBJsalesSales Data with Leading IndicatorCSVDOCdatasetsBODBiochemical Oxygen Dema…

R语言 聊天词云图

准备聊天记录 建议使用QQ聊天记录&#xff0c;导出txt格式 进行文本分词并可视化 install.packages("wordcloud2") install.packages("jiebaR") install.packages("jiebaRD") library(wordcloud2) library(jiebaRD) library(jiebaR) enginew…