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

基于SpringBoot的外卖项目(详细开发过程)

基于SpringBoot+MyBatisPlus的外卖项目

  • 1、软件开发整体介绍
    • 软件开发流程
    • 角色分工
  • 2、外卖项目介绍
    • 项目介绍
    • 产品展示
      • 后台系统管理
      • 移动端
    • 技术选型
    • 功能结构
    • 角色
  • 3、开发环境的搭建
    • 开发环境说明
    • 建库
    • 建表
    • Maven项目搭建
      • 项目的目录结构
      • pom.xml
      • application.yml
      • ReggieApplication启动类
      • 配置静态资源映射
  • 4、登录功能
    • 4.1、后台登录功能
      • 需求分析
      • 代码编写
        • R.java
        • 实体类
        • EmployeeMapper
        • EmployeeService
        • EmployeeServiceImpl
        • EmployeeController
        • 页面展示
    • 4.2、后台登出功能
      • 需求分析
      • 代码编写
      • 页面展示
    • 4.3、完善登录功能
      • 问题分析
      • 代码编写
      • LoginCheckFilter
  • 5、员工管理
    • 5.1、新增员工
      • 需求分析
      • 数据模型
      • 代码开发
      • 代码编写
      • 异常捕获
    • 小结
    • 5.2、员工信息分页查询
      • 需求分析
      • 代码开发
        • MyBatisPlusConfig配置分页插件
    • 5.3、启用/禁用员工账号
      • 需求分析
      • 代码编写
        • 编写一个通用的update方法
      • 功能测试
      • 功能修复
    • 5.3、编辑员工
      • 需求分析
      • 代码编写
    • 5.4、公共字段自动填充
      • 问题分析
      • 代码实现
      • 功能完善
        • ThreadLocal
  • 6、分类管理
    • 6.1、新增菜品分类
      • 需求分析
      • 数据模型
      • 代码开发
    • 6.1、新增菜品的分页查询
      • 需求分析
      • 代码开发
    • 6.2、删除分类
      • 需求分析
      • 代码开发
      • 功能完善
        • GlobalExceptionHandler
        • **CustomException**
        • CategoryServiceImpl
    • 6.3、修改分类
      • 需求分析
      • 代码编写
  • 7、菜品管理
    • 7.1、文件上传下载
      • 文件上传介绍
      • 文件下载介绍
      • 文件上传代码实现
      • 文件下载代码实现
    • 7.2、新增菜品
      • 需求分析
      • 数据模型
      • 代码开发
        • DishServiceImpl
        • DishController
    • 7.3、菜品信息分页查询
      • 需求分析
      • 代码开发
        • 难点
    • 7.4、修改菜品
      • 需求分析
      • 代码开发
        • controller
        • DishServiceImpl
    • 7.5、修改菜品的停/起售状态
      • DishController
      • DishServiceImpl
    • 7.6、删除菜品
  • 8、套餐管理
    • 8.1、新增套餐
      • 需求分析
      • 数据模型
      • 代码开发
        • DishController
        • SetmealDishController
        • SetmealServiceImpl
    • 8.2、套餐信息分页查询
      • 需求分析
      • 代码开发
    • 8.3、删除套餐
      • 需求分析
      • 代码开发
        • SetmealController
        • SetmealServiceImpl
    • 8.4、修改套餐
        • SetmealController
        • SetmealService
        • SetmealServiceImpl
    • 8.5、停售、启售套餐
      • SetmealController
      • SetmealServiceImpl
  • 9、前端--手机验证码登录
    • 9.1、短信发送
      • 阿里云短信服务
      • 设置签名
      • 添加模板详情
      • 设置AccessKey
      • 添加权限
      • 购买短信免费试用包
      • 代码开发
        • pom
        • 导入utils工具类
    • 9.2、手机验证码登录
      • 需求分析
      • 数据模型
      • 代码开发
        • 移动端页面放行的请求
        • UserController
  • 10、前端--导入用户地址簿
    • 需求分析
    • 数据模型
    • 代码开发
      • AddressBookController
  • 11、前端--菜品展示
    • 需求分析
    • 代码开发
      • 展示flavor口味信息
      • 套餐信息展示
  • 12、前端--购物车
    • 需求分析
    • 数据模型
    • 代码开发
  • 13、前端--用户下单
    • 需求分析
    • 数据模型
    • 代码开发
      • OrderController
      • OrderService
      • OrderServiceImpl
  • 14、代码托管
    • Git版本管理
    • Gitee
    • Github
    • 项目所需资料

申明: 未经许可,禁止以任何形式转载,若要引用,请标注链接地址。 全文共计86935字,阅读大概需要3分钟
更多学习内容, 欢迎关注我的个人公众号:不懂开发的程序猿

写在前面的几句话:
【警告】本篇博客较长,若引起阅读不适,建议收藏,稍后再读
【说明】该外卖项目是基于SpringBoot + MyBatisPlus为框架来开发的,前端页面框架都是现成的,只需要Java后端开发程序员编写对应的接口功能和服务,是一个很不错的练手项目。项目也非常适合作为大学生的课设,毕设
【文档】本篇博客详细介绍了该外卖项目的开发步骤,如果需要写课程设计或本科毕业论文文档,建议参考我下面这篇博客,内有详细的文档说明

点餐平台文档说明

1、软件开发整体介绍

软件开发流程

在这里插入图片描述

角色分工

在这里插入图片描述

2、外卖项目介绍

项目介绍

分为后台系统管理移动端两部分

后台系统管理供商家:对菜品、套餐、订单等进行管理维护等

移动端供消费者:在线浏览,添加购物车,下单 等

3步开发思路:

第一:主要实现基本需求,其中移动端应用通过H5实现,用户可以通过手机浏览器访问。

第二:主要针对移动端应用进行改进,使用微信小程序实现,用户使用起来更加方便。

第三:主要针对系统进行优化升级,提高系统的访问性能。

产品展示

后台系统管理

登录页
在这里插入图片描述

员工管理页
在这里插入图片描述

分类管理
在这里插入图片描述

菜品管理
在这里插入图片描述

套餐管理
在这里插入图片描述

订单明细
在这里插入图片描述

移动端

登录页
在这里插入图片描述

首页
在这里插入图片描述

下单确认页
在这里插入图片描述

下单成功页
在这里插入图片描述

个人中心页
在这里插入图片描述

地址管理页
在这里插入图片描述

历史订单页
在这里插入图片描述

技术选型

在这里插入图片描述

功能结构

在这里插入图片描述

角色

在这里插入图片描述

3、开发环境的搭建

开发环境说明

工具版本
后台SpringBoot + MyBatisPlus
服务器Tomcat 8.5.73
数据库MySQL 8.0.28
Build ToolsMaven 3.8.5
前端Vue + ElementUI
开发工具IDEA 2022.3
版本管理工具Git

建库

在这里插入图片描述

建表

/*
SQLyog Ultimate v12.08 (64 bit)
MySQL - 8.0.27 : Database - reggie
*********************************************************************
*//*!40101 SET NAMES utf8 */;/*!40101 SET SQL_MODE=''*/;/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`reggie` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;USE `reggie`;/*Table structure for table `address_book` */DROP TABLE IF EXISTS `address_book`;CREATE TABLE `address_book` (`id` bigint NOT NULL COMMENT '主键',`user_id` bigint NOT NULL COMMENT '用户id',`consignee` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '收货人',`sex` tinyint NOT NULL COMMENT '性别 0 女 1 男',`phone` varchar(11) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '手机号',`province_code` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '省级区划编号',`province_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '省级名称',`city_code` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '市级区划编号',`city_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '市级名称',`district_code` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '区级区划编号',`district_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '区级名称',`detail` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '详细地址',`label` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '标签',`is_default` tinyint(1) NOT NULL DEFAULT '0' COMMENT '默认 0 否 1是',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',`create_user` bigint NOT NULL COMMENT '创建人',`update_user` bigint NOT NULL COMMENT '修改人',`is_deleted` int NOT NULL DEFAULT '0' COMMENT '是否删除',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='地址管理';/*Data for the table `address_book` */insert  into `address_book`(`id`,`user_id`,`consignee`,`sex`,`phone`,`province_code`,`province_name`,`city_code`,`city_name`,`district_code`,`district_name`,`detail`,`label`,`is_default`,`create_time`,`update_time`,`create_user`,`update_user`,`is_deleted`) values (1417414526093082626,1417012167126876162,'小明',1,'13812345678',NULL,NULL,NULL,NULL,NULL,NULL,'昌平区金燕龙办公楼','公司',1,'2021-07-20 17:22:12','2021-07-20 17:26:33',1417012167126876162,1417012167126876162,0),(1417414926166769666,1417012167126876162,'小李',1,'13512345678',NULL,NULL,NULL,NULL,NULL,NULL,'测试','家',0,'2021-07-20 17:23:47','2021-07-20 17:23:47',1417012167126876162,1417012167126876162,0),(1628270733663694849,1627997218788163586,'金阳',1,'17671789248',NULL,NULL,NULL,NULL,NULL,NULL,'湖北工业大学','学校',1,'2023-02-22 13:49:29','2023-02-22 13:49:32',1627997218788163586,1627997218788163586,0);/*Table structure for table `category` */DROP TABLE IF EXISTS `category`;CREATE TABLE `category` (`id` bigint NOT NULL COMMENT '主键',`type` int DEFAULT NULL COMMENT '类型   1 菜品分类 2 套餐分类',`name` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '分类名称',`sort` int NOT NULL DEFAULT '0' COMMENT '顺序',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',`create_user` bigint NOT NULL COMMENT '创建人',`update_user` bigint NOT NULL COMMENT '修改人',PRIMARY KEY (`id`) USING BTREE,UNIQUE KEY `idx_category_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='菜品及套餐分类';/*Data for the table `category` */insert  into `category`(`id`,`type`,`name`,`sort`,`create_time`,`update_time`,`create_user`,`update_user`) values (1397844263642378242,1,'湘菜',1,'2021-05-27 09:16:58','2023-02-19 16:51:09',1,1),(1397844303408574465,1,'川菜',2,'2021-05-27 09:17:07','2021-06-02 14:27:22',1,1),(1397844391040167938,1,'粤菜',3,'2021-05-27 09:17:28','2021-07-09 14:37:13',1,1),(1413341197421846529,1,'饮品',11,'2021-07-09 11:36:15','2021-07-09 14:39:15',1,1),(1413342269393674242,2,'商务套餐',5,'2021-07-09 11:40:30','2021-07-09 14:43:45',1,1),(1413384954989060097,1,'主食',12,'2021-07-09 14:30:07','2021-07-09 14:39:19',1,1),(1413386191767674881,2,'儿童套餐',6,'2021-07-09 14:35:02','2021-07-09 14:39:05',1,1),(1627130608250593281,1,'湖北菜',4,'2023-02-19 10:19:02','2023-02-19 10:19:02',1,1);/*Table structure for table `dish` */DROP TABLE IF EXISTS `dish`;CREATE TABLE `dish` (`id` bigint NOT NULL COMMENT '主键',`name` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '菜品名称',`category_id` bigint NOT NULL COMMENT '菜品分类id',`price` decimal(10,2) DEFAULT NULL COMMENT '菜品价格',`code` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '商品码',`image` varchar(200) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '图片',`description` varchar(400) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '描述信息',`status` int NOT NULL DEFAULT '1' COMMENT '0 停售 1 起售',`sort` int NOT NULL DEFAULT '0' COMMENT '顺序',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',`create_user` bigint NOT NULL COMMENT '创建人',`update_user` bigint NOT NULL COMMENT '修改人',`is_deleted` int NOT NULL DEFAULT '0' COMMENT '是否删除',PRIMARY KEY (`id`) USING BTREE,UNIQUE KEY `idx_dish_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='菜品管理';/*Data for the table `dish` */insert  into `dish`(`id`,`name`,`category_id`,`price`,`code`,`image`,`description`,`status`,`sort`,`create_time`,`update_time`,`create_user`,`update_user`,`is_deleted`) values (1628019384179052546,'红烧肉',1397844263642378242,'3900.00','','90c9f385-5c18-491a-90f2-a4c8df198376.jpg','红烧肉',1,0,'2023-02-21 21:10:43','2023-02-21 21:10:43',1627997218788163586,1627997218788163586,0),(1628019727558332417,'麻辣鸡丝',1397844303408574465,'3900.00','','b19c64b2-378d-43d9-975f-2367bcc99e70.jpg','麻辣鸡丝',1,0,'2023-02-21 21:12:05','2023-02-21 21:12:05',1627997218788163586,1627997218788163586,0),(1628020011776954369,'辣子鸡',1627130608250593281,'4900.00','','d79ac164-8e43-4478-9d57-539764d1c5a8.jpg','来自鲜嫩美味的小鸡,值得一尝',1,0,'2023-02-21 21:13:13','2023-02-22 14:42:06',1627997218788163586,1627997218788163586,0),(1628020274659151874,'基围虾',1397844263642378242,'5900.00','','05010fb3-c055-41ff-8da8-4d941daea332.jpg','基围虾',1,0,'2023-02-21 21:14:15','2023-02-21 21:14:15',1627997218788163586,1627997218788163586,0),(1628020414488858625,'麻辣兔头',1397844303408574465,'12800.00','','703fb335-5593-49be-a629-e2522344212d.jpg','麻辣兔头',1,0,'2023-02-21 21:14:49','2023-02-21 21:14:49',1627997218788163586,1627997218788163586,0),(1628020624501854210,'邵阳猪血丸子',1397844391040167938,'5900.00','','79f6db2d-99d9-40f0-adee-a6750036d40e.jpg','邵阳猪血丸子',1,0,'2023-02-21 21:15:39','2023-02-21 21:15:39',1627997218788163586,1627997218788163586,0),(1628020855322791938,'烤乳猪',1397844391040167938,'9900.00','','8197826f-8bcd-44a1-9d0e-e742b0265e7d.jpeg','白切鸡',1,0,'2023-02-21 21:16:34','2023-02-21 21:19:39',1627997218788163586,1627997218788163586,0),(1628020978719215617,'脆皮烧鹅',1627130608250593281,'15800.00','','3d6188da-68f1-4299-89fd-04c7ab744110.jpeg','脆皮烧鹅',1,0,'2023-02-21 21:17:03','2023-02-22 14:41:44',1627997218788163586,1627997218788163586,0),(1628021120151146497,'上汤焗龙虾',1627130608250593281,'15800.00','','d2dbe897-3b8b-4e5c-99d8-b7ca159ba5b9.jpeg','上汤焗龙虾',1,0,'2023-02-21 21:17:37','2023-02-22 14:41:25',1627997218788163586,1627997218788163586,0),(1628021265471197185,'宫保鸡丁',1397844303408574465,'6900.00','','95f8b479-ae76-4107-9b08-3c62ae7f7fd0.jpg','宫保鸡丁',1,0,'2023-02-21 21:18:12','2023-02-22 14:40:23',1627997218788163586,1627997218788163586,0),(1628021771191013377,'白切鸡',1397844391040167938,'7900.00','','b5d537cf-0d6c-42ae-9210-94c981087d52.jpeg','白切鸡',1,0,'2023-02-21 21:20:12','2023-02-21 21:20:12',1627997218788163586,1627997218788163586,0),(1628022122845655041,'青椒炖鸡丁',1627130608250593281,'9900.00','','9b7494ee-1714-40ee-a94e-18c769678671.jpg','青椒炖鸡丁',1,0,'2023-02-21 21:21:36','2023-02-21 21:21:36',1627997218788163586,1627997218788163586,0),(1628022255993835522,'老火靓汤',1627130608250593281,'10900.00','','a72af50a-264c-4cf1-9da0-28e1eb98aa5c.jpeg','老火靓汤',1,0,'2023-02-21 21:22:08','2023-02-21 21:22:08',1627997218788163586,1627997218788163586,0),(1628022421907918850,'清蒸河鲜海鲜',1397844303408574465,'2900.00','','06b6c68f-db38-4bff-a8f4-131830291cec.jpg','清蒸河鲜海鲜',1,0,'2023-02-21 21:22:47','2023-02-21 21:22:47',1627997218788163586,1627997218788163586,0),(1628022523112280066,'王老吉',1413341197421846529,'500.00','','3e7ab2fe-01fa-4eb6-828e-b7998583a4e1.png','王老吉',1,0,'2023-02-21 21:23:11','2023-02-21 21:23:11',1627997218788163586,1627997218788163586,0),(1628022754352648193,'麻辣水煮鱼',1397844391040167938,'6500.00','','5f614bfa-f62c-4d5d-a4e3-852d6ce53d62.jpeg','麻辣水煮鱼',1,0,'2023-02-21 21:24:07','2023-02-22 14:40:56',1627997218788163586,1627997218788163586,0),(1628022918689673218,'清炒素食',1627130608250593281,'1900.00','','d8783e07-a8da-4e4e-8826-0c0e6990a08f.jpg','清炒素食',1,0,'2023-02-21 21:24:46','2023-02-21 21:24:46',1627997218788163586,1627997218788163586,0),(1628023021122965506,'啤酒',1413341197421846529,'1000.00','','bbfe22ba-9bd5-486a-ae83-22e108dddc47.png','啤酒',1,0,'2023-02-21 21:25:10','2023-02-21 21:25:10',1627997218788163586,1627997218788163586,0),(1628023133450620930,'麻辣鱼片',1397844303408574465,'3900.00','','ffdbeb37-0fbe-4190-a52a-3a16478f366e.jpg','麻辣鱼片',1,0,'2023-02-21 21:25:37','2023-02-21 21:25:37',1627997218788163586,1627997218788163586,0),(1628023363927625729,'烤乳鸽',1397844391040167938,'7900.00','','a1848e46-eb33-4957-bd77-039caaee79c2.jpeg','烤乳鸽',1,0,'2023-02-21 21:26:32','2023-02-21 21:26:32',1627997218788163586,1627997218788163586,0),(1628023490318782465,'大米饭',1413384954989060097,'500.00','','d19db29f-c016-410d-ac01-a3742ea1ea3c.png','大米饭',1,0,'2023-02-21 21:27:02','2023-02-21 21:27:02',1627997218788163586,1627997218788163586,0),(1628023694518472706,'辣子鸡丁',1397844263642378242,'3900.00','','c67657d7-4cbf-4d0c-b20c-7ab66ad52514.jpg','辣子鸡丁',1,0,'2023-02-21 21:27:51','2023-02-21 21:27:51',1627997218788163586,1627997218788163586,0),(1628023841423970305,'口味蛇',1627130608250593281,'8800.00','','3d486c18-6dd8-4464-a087-bd93cfc987bf.jpg','口味蛇',1,0,'2023-02-21 21:28:26','2023-02-21 21:28:26',1627997218788163586,1627997218788163586,0);/*Table structure for table `dish_flavor` */DROP TABLE IF EXISTS `dish_flavor`;CREATE TABLE `dish_flavor` (`id` bigint NOT NULL COMMENT '主键',`dish_id` bigint NOT NULL COMMENT '菜品',`name` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '口味名称',`value` varchar(500) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '口味数据list',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',`create_user` bigint NOT NULL COMMENT '创建人',`update_user` bigint NOT NULL COMMENT '修改人',`is_deleted` int NOT NULL DEFAULT '0' COMMENT '是否删除',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='菜品口味关系表';/*Data for the table `dish_flavor` */insert  into `dish_flavor`(`id`,`dish_id`,`name`,`value`,`create_time`,`update_time`,`create_user`,`update_user`,`is_deleted`) values (1628019384321658881,1628019384179052546,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:10:43','2023-02-21 21:10:43',1627997218788163586,1627997218788163586,0),(1628019384321658882,1628019384179052546,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:10:43','2023-02-21 21:10:43',1627997218788163586,1627997218788163586,0),(1628019727621246978,1628019727558332417,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:12:05','2023-02-21 21:12:05',1627997218788163586,1627997218788163586,0),(1628019727621246979,1628019727558332417,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:12:05','2023-02-21 21:12:05',1627997218788163586,1627997218788163586,0),(1628019727621246980,1628019727558332417,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:12:05','2023-02-21 21:12:05',1627997218788163586,1627997218788163586,0),(1628020274726260738,1628020274659151874,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:14:15','2023-02-21 21:14:15',1627997218788163586,1627997218788163586,0),(1628020274726260739,1628020274659151874,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:14:15','2023-02-21 21:14:15',1627997218788163586,1627997218788163586,0),(1628020274726260740,1628020274659151874,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:14:15','2023-02-21 21:14:15',1627997218788163586,1627997218788163586,0),(1628020414488858626,1628020414488858625,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:14:49','2023-02-21 21:14:49',1627997218788163586,1627997218788163586,0),(1628020414488858627,1628020414488858625,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:14:49','2023-02-21 21:14:49',1627997218788163586,1627997218788163586,0),(1628020624573157378,1628020624501854210,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:15:39','2023-02-21 21:15:39',1627997218788163586,1627997218788163586,0),(1628020624573157379,1628020624501854210,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:15:39','2023-02-21 21:15:39',1627997218788163586,1627997218788163586,0),(1628020855389900802,1628020855322791938,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:19:39','2023-02-21 21:19:39',1627997218788163586,1627997218788163586,0),(1628020855389900803,1628020855322791938,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:19:39','2023-02-21 21:19:39',1627997218788163586,1627997218788163586,0),(1628021771191013378,1628021771191013377,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:20:12','2023-02-21 21:20:12',1627997218788163586,1627997218788163586,0),(1628021771191013379,1628021771191013377,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:20:12','2023-02-21 21:20:12',1627997218788163586,1627997218788163586,0),(1628022122971484162,1628022122845655041,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:21:36','2023-02-21 21:21:36',1627997218788163586,1627997218788163586,0),(1628022122971484163,1628022122845655041,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:21:36','2023-02-21 21:21:36',1627997218788163586,1627997218788163586,0),(1628022256186773505,1628022255993835522,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:22:08','2023-02-21 21:22:08',1627997218788163586,1627997218788163586,0),(1628022256186773506,1628022255993835522,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:22:08','2023-02-21 21:22:08',1627997218788163586,1627997218788163586,0),(1628022421975027713,1628022421907918850,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:22:47','2023-02-21 21:22:47',1627997218788163586,1627997218788163586,0),(1628022421975027714,1628022421907918850,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:22:47','2023-02-21 21:22:47',1627997218788163586,1627997218788163586,0),(1628022523175194626,1628022523112280066,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:23:11','2023-02-21 21:23:11',1627997218788163586,1627997218788163586,0),(1628022918823890945,1628022918689673218,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:24:46','2023-02-21 21:24:46',1627997218788163586,1627997218788163586,0),(1628022918823890946,1628022918689673218,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:24:46','2023-02-21 21:24:46',1627997218788163586,1627997218788163586,0),(1628023021190074370,1628023021122965506,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:25:10','2023-02-21 21:25:10',1627997218788163586,1627997218788163586,0),(1628023133576450049,1628023133450620930,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:25:37','2023-02-21 21:25:37',1627997218788163586,1627997218788163586,0),(1628023133576450050,1628023133450620930,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:25:37','2023-02-21 21:25:37',1627997218788163586,1627997218788163586,0),(1628023364061843457,1628023363927625729,'甜味','[\"无糖\",\"少糖\",\"半糖\",\"多糖\",\"全糖\"]','2023-02-21 21:26:32','2023-02-21 21:26:32',1627997218788163586,1627997218788163586,0),(1628023364061843458,1628023363927625729,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:26:32','2023-02-21 21:26:32',1627997218788163586,1627997218788163586,0),(1628023490448805890,1628023490318782465,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:27:02','2023-02-21 21:27:02',1627997218788163586,1627997218788163586,0),(1628023694585581569,1628023694518472706,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:27:51','2023-02-21 21:27:51',1627997218788163586,1627997218788163586,0),(1628023694585581570,1628023694518472706,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:27:51','2023-02-21 21:27:51',1627997218788163586,1627997218788163586,0),(1628023841553993729,1628023841423970305,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:28:26','2023-02-21 21:28:26',1627997218788163586,1627997218788163586,0),(1628023841553993730,1628023841423970305,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:28:26','2023-02-21 21:28:26',1627997218788163586,1627997218788163586,0),(1628283539888816129,1628021265471197185,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-22 14:40:23','2023-02-22 14:40:23',1627997218788163586,1627997218788163586,0),(1628283539888816130,1628021265471197185,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-22 14:40:23','2023-02-22 14:40:23',1627997218788163586,1627997218788163586,0),(1628283681786314754,1628022754352648193,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-22 14:40:56','2023-02-22 14:40:56',1627997218788163586,1627997218788163586,0),(1628283681786314755,1628022754352648193,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-22 14:40:56','2023-02-22 14:40:56',1627997218788163586,1627997218788163586,0),(1628283800552226817,1628021120151146497,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-22 14:41:25','2023-02-22 14:41:25',1627997218788163586,1627997218788163586,0),(1628283800552226818,1628021120151146497,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-22 14:41:25','2023-02-22 14:41:25',1627997218788163586,1627997218788163586,0),(1628283883154849793,1628020978719215617,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-22 14:41:44','2023-02-22 14:41:44',1627997218788163586,1627997218788163586,0),(1628283883154849794,1628020978719215617,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-22 14:41:44','2023-02-22 14:41:44',1627997218788163586,1627997218788163586,0),(1628283974536151041,1628020011776954369,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-22 14:42:06','2023-02-22 14:42:06',1627997218788163586,1627997218788163586,0),(1628283974536151042,1628020011776954369,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-22 14:42:06','2023-02-22 14:42:06',1627997218788163586,1627997218788163586,0);/*Table structure for table `employee` */DROP TABLE IF EXISTS `employee`;CREATE TABLE `employee` (`id` bigint NOT NULL COMMENT '主键',`name` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '姓名',`username` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '用户名',`password` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '密码',`phone` varchar(11) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '手机号',`sex` varchar(2) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '性别',`id_number` varchar(18) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '身份证号',`status` int NOT NULL DEFAULT '1' COMMENT '状态 0:禁用,1:正常',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',`create_user` bigint NOT NULL COMMENT '创建人',`update_user` bigint NOT NULL COMMENT '修改人',PRIMARY KEY (`id`) USING BTREE,UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='员工信息';/*Data for the table `employee` */insert  into `employee`(`id`,`name`,`username`,`password`,`phone`,`sex`,`id_number`,`status`,`create_time`,`update_time`,`create_user`,`update_user`) values (1,'管理员','admin','e10adc3949ba59abbe56e057f20f883e','13812312312','1','110101199001010047',1,'2021-05-06 17:20:07','2021-05-10 02:24:09',1,1),(1626857776597762049,'张三1','zhangsan','e10adc3949ba59abbe56e057f20f883e','17671789248','1','421181199805171311',1,'2023-02-18 16:14:54','2023-02-18 22:06:50',1,1),(1626945547559514113,'小李','test001','e10adc3949ba59abbe56e057f20f883e','17612345678','1','421181123456781234',1,'2023-02-18 22:04:04','2023-02-19 08:52:25',1,1);/*Table structure for table `order_detail` */DROP TABLE IF EXISTS `order_detail`;CREATE TABLE `order_detail` (`id` bigint NOT NULL COMMENT '主键',`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '名字',`image` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '图片',`order_id` bigint NOT NULL COMMENT '订单id',`dish_id` bigint DEFAULT NULL COMMENT '菜品id',`setmeal_id` bigint DEFAULT NULL COMMENT '套餐id',`dish_flavor` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '口味',`number` int NOT NULL DEFAULT '1' COMMENT '数量',`amount` decimal(10,2) NOT NULL COMMENT '金额',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='订单明细表';/*Data for the table `order_detail` */insert  into `order_detail`(`id`,`name`,`image`,`order_id`,`dish_id`,`setmeal_id`,`dish_flavor`,`number`,`amount`) values (1628281691748474882,'儿童套餐A','17fb2dcf-c06a-46c4-8ba6-8cb461d84031.jpg',1628281691555536898,NULL,1628024994765295618,NULL,1,'59.00'),(1628281691748474883,'辣子鸡丁','c67657d7-4cbf-4d0c-b20c-7ab66ad52514.jpg',1628281691555536898,1628023694518472706,NULL,'不要香菜,中辣',1,'39.00'),(1628281691748474884,'麻辣鱼片','ffdbeb37-0fbe-4190-a52a-3a16478f366e.jpg',1628281691555536898,1628023133450620930,NULL,'不要蒜,中辣',1,'39.00'),(1628281691748474885,'宫保鸡丁','95f8b479-ae76-4107-9b08-3c62ae7f7fd0.jpg',1628281691555536898,1628021265471197185,NULL,NULL,1,'69.00'),(1628281691748474886,'麻辣兔头','703fb335-5593-49be-a629-e2522344212d.jpg',1628281691555536898,1628020414488858625,NULL,'去冰,中辣',1,'128.00'),(1628281691811389441,'商务套餐A','fb706fe0-b57f-46da-9f70-f209cc489f39.jpg',1628281691555536898,NULL,1628024830898032642,NULL,1,'99.00'),(1628302223755788290,'辣子鸡丁','c67657d7-4cbf-4d0c-b20c-7ab66ad52514.jpg',1628302223562850306,1628023694518472706,NULL,'不要蒜,微辣',1,'39.00'),(1628302223755788291,'商务套餐A','fb706fe0-b57f-46da-9f70-f209cc489f39.jpg',1628302223562850306,NULL,1628024830898032642,NULL,1,'99.00'),(1628302223755788292,'儿童套餐A','17fb2dcf-c06a-46c4-8ba6-8cb461d84031.jpg',1628302223562850306,NULL,1628024994765295618,NULL,1,'59.00');/*Table structure for table `orders` */DROP TABLE IF EXISTS `orders`;CREATE TABLE `orders` (`id` bigint NOT NULL COMMENT '主键',`number` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '订单号',`status` int NOT NULL DEFAULT '1' COMMENT '订单状态 1待付款,2待派送,3已派送,4已完成,5已取消',`user_id` bigint NOT NULL COMMENT '下单用户',`address_book_id` bigint NOT NULL COMMENT '地址id',`order_time` datetime NOT NULL COMMENT '下单时间',`checkout_time` datetime NOT NULL COMMENT '结账时间',`pay_method` int NOT NULL DEFAULT '1' COMMENT '支付方式 1微信,2支付宝',`amount` decimal(10,2) NOT NULL COMMENT '实收金额',`remark` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '备注',`phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,`address` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,`user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,`consignee` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='订单表';/*Data for the table `orders` */insert  into `orders`(`id`,`number`,`status`,`user_id`,`address_book_id`,`order_time`,`checkout_time`,`pay_method`,`amount`,`remark`,`phone`,`address`,`user_name`,`consignee`) values (1628281691555536898,'1628281691555536898',2,1627997218788163586,1628270733663694849,'2023-02-22 14:33:02','2023-02-22 14:33:02',1,'433.00','','17671789248','湖北工业大学',NULL,'金阳'),(1628302223562850306,'1628302223562850306',2,1627997218788163586,1628270733663694849,'2023-02-22 15:54:37','2023-02-22 15:54:37',1,'197.00','','17671789248','湖北工业大学',NULL,'金阳');/*Table structure for table `setmeal` */DROP TABLE IF EXISTS `setmeal`;CREATE TABLE `setmeal` (`id` bigint NOT NULL COMMENT '主键',`category_id` bigint NOT NULL COMMENT '菜品分类id',`name` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '套餐名称',`price` decimal(10,2) NOT NULL COMMENT '套餐价格',`status` int DEFAULT NULL COMMENT '状态 0:停用 1:启用',`code` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '编码',`description` varchar(512) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '描述信息',`image` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '图片',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',`create_user` bigint NOT NULL COMMENT '创建人',`update_user` bigint NOT NULL COMMENT '修改人',`is_deleted` int NOT NULL DEFAULT '0' COMMENT '是否删除',PRIMARY KEY (`id`) USING BTREE,UNIQUE KEY `idx_setmeal_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='套餐';/*Data for the table `setmeal` */insert  into `setmeal`(`id`,`category_id`,`name`,`price`,`status`,`code`,`description`,`image`,`create_time`,`update_time`,`create_user`,`update_user`,`is_deleted`) values (1628024830898032642,1413342269393674242,'商务套餐A','9900.00',1,'','商务套餐A','fb706fe0-b57f-46da-9f70-f209cc489f39.jpg','2023-02-21 21:32:22','2023-02-21 21:32:22',1627997218788163586,1627997218788163586,0),(1628024994765295618,1413386191767674881,'儿童套餐A','5900.00',1,'','儿童套餐A','17fb2dcf-c06a-46c4-8ba6-8cb461d84031.jpg','2023-02-21 21:33:01','2023-02-21 21:33:01',1627997218788163586,1627997218788163586,0);/*Table structure for table `setmeal_dish` */DROP TABLE IF EXISTS `setmeal_dish`;CREATE TABLE `setmeal_dish` (`id` bigint NOT NULL COMMENT '主键',`setmeal_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '套餐id ',`dish_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '菜品id',`name` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '菜品名称 (冗余字段)',`price` decimal(10,2) DEFAULT NULL COMMENT '菜品原价(冗余字段)',`copies` int NOT NULL COMMENT '份数',`sort` int NOT NULL DEFAULT '0' COMMENT '排序',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',`create_user` bigint NOT NULL COMMENT '创建人',`update_user` bigint NOT NULL COMMENT '修改人',`is_deleted` int NOT NULL DEFAULT '0' COMMENT '是否删除',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='套餐菜品关系';/*Data for the table `setmeal_dish` */insert  into `setmeal_dish`(`id`,`setmeal_id`,`dish_id`,`name`,`price`,`copies`,`sort`,`create_time`,`update_time`,`create_user`,`update_user`,`is_deleted`) values (1628024830960947201,'1628024830898032642','1628023694518472706','辣子鸡丁','3900.00',1,0,'2023-02-21 21:32:22','2023-02-21 21:32:22',1627997218788163586,1627997218788163586,0),(1628024830960947202,'1628024830898032642','1628023490318782465','大米饭','500.00',1,0,'2023-02-21 21:32:22','2023-02-21 21:32:22',1627997218788163586,1627997218788163586,0),(1628024830960947203,'1628024830898032642','1628023021122965506','啤酒','1000.00',1,0,'2023-02-21 21:32:22','2023-02-21 21:32:22',1627997218788163586,1627997218788163586,0),(1628024830960947204,'1628024830898032642','1628023363927625729','烤乳鸽','7900.00',1,0,'2023-02-21 21:32:22','2023-02-21 21:32:22',1627997218788163586,1627997218788163586,0),(1628024994832404481,'1628024994765295618','1628023490318782465','大米饭','500.00',1,0,'2023-02-21 21:33:01','2023-02-21 21:33:01',1627997218788163586,1627997218788163586,0),(1628024994832404482,'1628024994765295618','1628022523112280066','王老吉','500.00',1,0,'2023-02-21 21:33:01','2023-02-21 21:33:01',1627997218788163586,1627997218788163586,0),(1628024994832404483,'1628024994765295618','1628022918689673218','清炒素食','1900.00',1,0,'2023-02-21 21:33:01','2023-02-21 21:33:01',1627997218788163586,1627997218788163586,0),(1628024994832404484,'1628024994765295618','1628023363927625729','烤乳鸽','7900.00',1,0,'2023-02-21 21:33:01','2023-02-21 21:33:01',1627997218788163586,1627997218788163586,0);/*Table structure for table `shopping_cart` */DROP TABLE IF EXISTS `shopping_cart`;CREATE TABLE `shopping_cart` (`id` bigint NOT NULL COMMENT '主键',`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '名称',`image` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '图片',`user_id` bigint NOT NULL COMMENT '主键',`dish_id` bigint DEFAULT NULL COMMENT '菜品id',`setmeal_id` bigint DEFAULT NULL COMMENT '套餐id',`dish_flavor` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '口味',`number` int NOT NULL DEFAULT '1' COMMENT '数量',`amount` decimal(10,2) NOT NULL COMMENT '金额',`create_time` datetime DEFAULT NULL COMMENT '创建时间',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='购物车';/*Data for the table `shopping_cart` *//*Table structure for table `user` */DROP TABLE IF EXISTS `user`;CREATE TABLE `user` (`id` bigint NOT NULL COMMENT '主键',`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '姓名',`phone` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '手机号',`sex` varchar(2) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '性别',`id_number` varchar(18) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '身份证号',`avatar` varchar(500) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '头像',`status` int DEFAULT '0' COMMENT '状态 0:禁用,1:正常',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='用户信息';/*Data for the table `user` */insert  into `user`(`id`,`name`,`phone`,`sex`,`id_number`,`avatar`,`status`) values (1627997218788163586,NULL,'17612349248',NULL,NULL,NULL,1);/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

数据表

在这里插入图片描述

Maven项目搭建

项目的目录结构

在这里插入图片描述

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.5</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.jerry</groupId><artifactId>reggie</artifactId><version>1.0</version><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><scope>compile</scope></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.23</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.4.5</version></plugin></plugins></build>
</project>

application.yml

server:port: 8080
spring:application:# 应用名称,可选项name: reggiedatasource:druid:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: root
mybatis-plus:configuration:#在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:id-type: ASSIGN_ID

ReggieApplication启动类

package com.jerry.reggie;import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** ClassName: ReggieApplication* Package: com.jerry.reggie* Description:** @Author jerry_jy* @Create 2023-02-16 13:50* @Version 1.0*/
@Slf4j
@SpringBootApplication
public class ReggieApplication {public static void main(String[] args) {SpringApplication.run(ReggieApplication.class, args);log.info("项目启动成功...");}
}

配置静态资源映射

SpringBoot访问静态资源默认会去resources/static或resources/templates目录下,如果不需要static或templates目录,那就手动使用配置类进行配置访问路径

package com.jerry.reggie.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;/*** ClassName: WebMvcConfig* Package: com.jerry.reggie.config* Description:** @Author jerry_jy* @Create 2023-02-16 14:16* @Version 1.0*/
@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {/*** 设置静态资源映射* @param registry*/@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {log.info("开始进行静态资源的映射...");registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");}
}

访问:http://localhost:8080/backend/index.html

在这里插入图片描述

4、登录功能

4.1、后台登录功能

需求分析

在这里插入图片描述

代码编写

vo类:将服务器和前端页面传递的数据封装好

R类是一个通用结果类,服务端响应的所有结果最终都会包装成此种类型返回给前端页面

R.java

package com.jerry.reggie.common;import lombok.Data;
import java.util.HashMap;
import java.util.Map;/*** 通用返回结果,服务器端响应的数据最终都会封装成此对象* @param <T>*/
@Data
public class R<T> {private Integer code; //编码:1成功,0和其它数字为失败private String msg; //错误信息private T data; //数据private Map map = new HashMap(); //动态数据public static <T> R<T> success(T object) {R<T> r = new R<T>();r.data = object;r.code = 1;return r;}public static <T> R<T> error(String msg) {R r = new R();r.msg = msg;r.code = 0;return r;}public R<T> add(String key, Object value) {this.map.put(key, value);return this;}}

实体类

package com.jerry.reggie.entity;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;/*** 员工实体类*/
@Data
public class Employee implements Serializable {private static final long serialVersionUID = 1L;private Long id;private String username;private String name;private String password;private String phone;private String sex;private String idNumber;//身份证号private Integer status;private LocalDateTime createTime;private LocalDateTime updateTime;@TableField(fill = FieldFill.INSERT)private Long createUser;@TableField(fill = FieldFill.INSERT_UPDATE)private Long updateUser;}

EmployeeMapper

package com.jerry.reggie.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jerry.reggie.entity.Employee;
import org.apache.ibatis.annotations.Mapper;/*** ClassName: EmployeeMApper* Package: com.jerry.reggie.mapper* Description:** @Author jerry_jy* @Create 2023-02-16 14:45* @Version 1.0*/
@Mapper
public interface EmployeeMapper extends BaseMapper<Employee> {
}

EmployeeService

package com.jerry.reggie.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.jerry.reggie.entity.Employee;/*** ClassName: EmployeeService* Package: com.jerry.reggie.service* Description:** @Author jerry_jy* @Create 2023-02-16 14:46* @Version 1.0*/
public interface EmployeeService extends IService<Employee> {
}

EmployeeServiceImpl

package com.jerry.reggie.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jerry.reggie.entity.Employee;
import com.jerry.reggie.mapper.EmployeeMapper;
import com.jerry.reggie.service.EmployeeService;
import org.springframework.stereotype.Service;/*** ClassName: EmployeeServiceImpl* Package: com.jerry.reggie.service.impl* Description:** @Author jerry_jy* @Create 2023-02-16 14:46* @Version 1.0*/@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {
}

EmployeeController

在这里插入图片描述

package com.jerry.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jerry.reggie.common.R;
import com.jerry.reggie.entity.Employee;
import com.jerry.reggie.service.EmployeeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Controller;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletRequest;/*** ClassName: EmployeeController* Package: com.jerry.reggie.controller* Description:** @Author jerry_jy* @Create 2023-02-16 14:52* @Version 1.0*/
@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {@Autowiredprivate EmployeeService employeeService;@PostMapping("/login")public R<Employee> login(@RequestBody Employee employee, HttpServletRequest request) {//@RequestBody用来接收前端传递给后端的`json`字符串中的数据的(请求体中的数据的),所以前端只能发送POST请求//1、将页面提交的密码password进行md5加密处理String pwd = employee.getPassword();pwd = DigestUtils.md5DigestAsHex(pwd.getBytes());// 2、根据页面提交的用户名username查询数据库]/*** 我自己写的是*         QueryWrapper<Employee> queryWrapper = new QueryWrapper<>();*         employeeService.getOne(queryWrapper.select(employee.getName()));* 查询出来的是null值*/LambdaQueryWrapper<Employee> wrapper = new LambdaQueryWrapper<>();//方法引用的语法格式(语法糖)wrapper.eq(Employee::getUsername,employee.getUsername());Employee emp = employeeService.getOne(wrapper);// 3、如果没有查询到则返回登录失败结果if (emp == null) {return R.error("登录失败");}//4、密码比对,如果不一致则返回登录失败结果if (!pwd.equals(emp.getPassword())) {return R.error("登录失败");}//5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果if (emp.getStatus()!=1){return R.error("员工账号已禁用");}// 6、登录成功,将员工id存入Session并返回登录成功结果Long empId = emp.getId();request.getSession().setAttribute("empId",empId);return R.success(emp);}
}

页面展示

http://localhost:8080/backend/page/login/login.html

http://localhost:8080/backend/index.html

4.2、后台登出功能

需求分析

在这里插入图片描述

代码编写

/*** 员工后台登出功能* @param request* @return*/
@PostMapping("/logout")
public R<String> logout(HttpServletRequest request) {//1、清理Session中的用户idrequest.getSession().removeAttribute("empId");// 2、返回结果return R.success("登出成功");
}

页面展示

4.3、完善登录功能

问题分析

在这里插入图片描述

代码编写

在这里插入图片描述

LoginCheckFilter

package com.jerry.reggie.filter;import com.alibaba.fastjson.JSON;
import com.jerry.reggie.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** ClassName: LoginCheckFilter* Package: com.jerry.reggie.filter* Description:** @Author jerry_jy* @Create 2023-02-16 21:50* @Version 1.0*/
@Slf4j
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
public class LoginCheckFilter implements Filter {//路径匹配,支持通配符public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;//1、获取本次请求的URIString uri = request.getRequestURI(); //   backend/index.htmllog.info("拦截到请求:{}", uri);//定义不需要处理的请求路径String[] urls = new String[]{"/employee/login","employee/logout","/backend/**","/front/**"};//2、判断本次请求是否需要处理boolean check = check(urls, uri);// 3、如果不需要处理,则直接放行if (check == true) {log.info("本次请求{}不需要处理" + uri);filterChain.doFilter(request, response);return;}//4、判断登录状态,如果已登录,则直接放行if (request.getSession().getAttribute("empId") != null) {log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("empId"));filterChain.doFilter(request, response);return;}log.info("用户未登录");// 5、如果未登录则返回未登录结果,通过输出流方式向客户端响应数据response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));return;}/*** 路径匹配,检查本次请求是否需要放行** @param urls* @param uri* @return*/public boolean check(String[] urls, String uri) {for (String url : urls) {boolean match = PATH_MATCHER.match(url, uri);if (match) {return true;}}return false;}
}

在这里插入图片描述

5、员工管理

5.1、新增员工

需求分析

在这里插入图片描述

数据模型

在这里插入图片描述

代码开发

在这里插入图片描述

代码编写

/*** 新增员工* @param employee* @return*/
@PostMapping
public R<String> save(@RequestBody Employee employee, HttpServletRequest request){log.info("新增员工,员工信息:{}",employee.toString());//设置员工的初始密码,需要进行MD5 加密处理employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));employee.setCreateTime(LocalDateTime.now());employee.setUpdateTime(LocalDateTime.now());//获得当前登录对象的idLong empId = (Long) request.getSession().getAttribute("empId");employee.setCreateUser(empId);employee.setUpdateUser(empId);employeeService.save(employee);return R.success("添加员工成功");
}

异常捕获

在这里插入图片描述

GlobalExceptionHandler

package com.jerry.reggie.common;/*** ClassName: GlobalExceptionHandler* Package: com.jerry.reggie.common* Description:** @Author jerry_jy* @Create 2023-02-18 16:21* @Version 1.0*/import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import java.sql.SQLIntegrityConstraintViolationException;/*** 全局异常捕获*/
@ControllerAdvice(annotations = {RestController.class, Controller.class})
@ResponseBody //要返回json数据时就写
@Slf4j
public class GlobalExceptionHandler {/*** 异常处理方法* @return*/@ExceptionHandler(SQLIntegrityConstraintViolationException.class)public R<String> exceptionHandler(SQLIntegrityConstraintViolationException exception){log.error(exception.getMessage());if (exception.getMessage().contains("Duplicate entry")){String[] strings = exception.getMessage().split(" ");String msg = strings[2] + "已存在";return R.error(msg);}return R.error("未知错误");}
}

小结

在这里插入图片描述

5.2、员工信息分页查询

需求分析

在这里插入图片描述

代码开发

在这里插入图片描述

MyBatisPlusConfig配置分页插件

package com.jerry.reggie.config;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** ClassName: MyBatisPlusConfig* Package: com.jerry.reggie.config* Description:** @Author jerry_jy* @Create 2023-02-18 17:16* @Version 1.0*//*** 配置MP的分页插件*/
@Configuration
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());return mybatisPlusInterceptor;}
}
/*** 员工信息分页查询** @param page* @param pageSize* @param name* @return*/
@GetMapping("/page")
public R<Page> page(int page, int pageSize, String name) {log.info("page = {}, pageSize = {}, name = {}", page, pageSize, name);//这里:只需要new page对象和构造好lambdaQueryWrapper//构造分页构造器Page<Employee> pageInfo = new Page<>(page, pageSize);//构造条件构造器LambdaQueryWrapper<Employee> lambdaQueryWrapper = new LambdaQueryWrapper<>();//添加一个过滤条件lambdaQueryWrapper.like(StringUtils.isNotEmpty(name), Employee::getName, name);//添加一个排序条件lambdaQueryWrapper.orderByDesc(Employee::getUpdateTime);//执行查询employeeService.page(pageInfo, lambdaQueryWrapper);return R.success(pageInfo);
}

5.3、启用/禁用员工账号

需求分析

在这里插入图片描述

在这里插入图片描述

代码编写

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

编写一个通用的update方法

在这里插入图片描述

/*** 根据id修改员工信息** @param employee* @return*/
@PutMapping
public R<String> update(HttpServletRequest request, @RequestBody Employee employee) {log.info(employee.toString());Long empId = (Long) request.getSession().getAttribute("empId");employee.setUpdateTime(LocalDateTime.now());employee.setUpdateUser(empId);employeeService.updateById(employee);return R.success("更新成功");
}

功能测试

原因:JS在处理Long型数据时,只能处理16位,也就是说,2^53次方,超过后就四舍五入,精度损失

在这里插入图片描述

功能修复

在这里插入图片描述

在这里插入图片描述

/*** 扩展mvc消息框架的转换器* @param converters*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {log.info("扩展消息转换器...");//创建消息转换器对象MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();//设置对象转换器,底层使用Jackson将Java对象转为jsonmessageConverter.setObjectMapper(new JacksonObjectMapper());//将上面的消息转换器对象追加到mvc框架的转换器集合中converters.add(0, messageConverter);
}

5.3、编辑员工

需求分析

在这里插入图片描述

代码编写

在这里插入图片描述

/*** 根据id查询员工信息** @param id* @return*/@GetMapping("/{id}")
public R<Employee> getById(@PathVariable Long id) {log.info("根据id 查询员工信息...");Employee employee = employeeService.getById(id);if (employee != null) {return R.success(employee);}return R.error("没有查询到对应的员工信息");
}

5.4、公共字段自动填充

问题分析

在这里插入图片描述

代码实现

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

功能完善

在这里插入图片描述

在这里插入图片描述

ThreadLocal

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

BaseContext

package com.jerry.reggie.common;/*** ClassName: BaseContext* Package: com.jerry.reggie.common* Description:** @Author jerry_jy* @Create 2023-02-19 9:00* @Version 1.0*//*** 基于ThreadLocal封装的工具类,用于保存和获取当前登录用户的id*/
public class BaseContext {private static ThreadLocal<Long> threadLocal= new ThreadLocal<>();public static void setCurrentId(Long id){threadLocal.set(id);}public static Long getCurrentId(){return threadLocal.get();}
}

6、分类管理

6.1、新增菜品分类

需求分析

在这里插入图片描述

在这里插入图片描述

数据模型

在这里插入图片描述

代码开发

在这里插入图片描述

在这里插入图片描述

6.1、新增菜品的分页查询

需求分析

在这里插入图片描述

代码开发

在这里插入图片描述

/*** 菜品分页查询* @param page* @param pageSize* @return*/
@GetMapping("/page")
public R<Page> page(int page, int pageSize){//分页构造器Page<Category> categoryPage = new Page<>();//条件构造器LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();//添加排序条件lambdaQueryWrapper.orderByAsc(Category::getSort);categoryService.page(categoryPage, lambdaQueryWrapper);return R.success(categoryPage);
}

6.2、删除分类

需求分析

在这里插入图片描述

代码开发

在这里插入图片描述

功能完善

在这里插入图片描述

GlobalExceptionHandler

/*** 异常处理方法* @return*/
@ExceptionHandler(CustomException.class)
public R<String> exceptionHandler(CustomException exception){log.error(exception.getMessage());return R.error(exception.getMessage());
}

CustomException

package com.jerry.reggie.common;/*** ClassName: CustomException* Package: com.jerry.reggie.common* Description:** @Author jerry_jy* @Create 2023-02-19 11:55* @Version 1.0*//*** 自定义业务异常类*/
public class CustomException extends RuntimeException{public CustomException(String message){super(message);}
}

CategoryServiceImpl

package com.jerry.reggie.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jerry.reggie.common.CustomException;
import com.jerry.reggie.entity.Category;
import com.jerry.reggie.entity.Dish;
import com.jerry.reggie.entity.Setmeal;
import com.jerry.reggie.mapper.CategoryMapper;
import com.jerry.reggie.service.CategoryService;
import com.jerry.reggie.service.DishService;
import com.jerry.reggie.service.SetmealService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;/*** ClassName: CategoryServiceImpl* Package: com.jerry.reggie.service.impl* Description:** @Author jerry_jy* @Create 2023-02-19 9:30* @Version 1.0*/
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {@Autowiredprivate DishService dishService;@Autowiredprivate SetmealService setmealService;/*** 根据id删除分类,删除之前需要进行判断* @param id*/@Overridepublic void remove(Long id) {LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();//添加查询条件,根据分类id查询dishLambdaQueryWrapper.eq(Dish::getCategoryId,id);int count1 = dishService.count(dishLambdaQueryWrapper);//查询当前分类是否关联了菜品,如果已经关联,抛出一个业务异常if (count1>0){//已经关联,抛出一个业务异常throw new CustomException("当前分类下关联了菜品,不能删除");}//查询当前分类是否关联了套餐,如果已经关联,抛出一个业务异常LambdaQueryWrapper<Setmeal> setmealLambdaQueryWrapper = new LambdaQueryWrapper<>();setmealLambdaQueryWrapper.eq(Setmeal::getCategoryId,id);int count2 = setmealService.count(setmealLambdaQueryWrapper);if (count2>0){//已经关联套餐,抛出一个业务异常throw new CustomException("当前分类下关联了套餐,不能删除");}//正常删除分类super.removeById(id);}
}
    /*** 根据id删除分类* @param id* @return*/@DeleteMappingpublic R<String> delete(Long id){log.info("删除分类:{}",id);//        categoryService.removeById(id);categoryService.remove(id);return R.success("分类信息删除成功");}

6.3、修改分类

需求分析

在这里插入图片描述

代码编写

/*** 根据id修改分类信息* @param category* @return*/
@PutMapping
public R<String> update(@RequestBody Category category){log.info("修改分类信息:{}",category);categoryService.updateById(category);return R.success("修改分类信息成功");
}

7、菜品管理

7.1、文件上传下载

文件上传介绍

在这里插入图片描述

在这里插入图片描述

文件下载介绍

在这里插入图片描述

文件上传代码实现

在这里插入图片描述

package com.jerry.reggie.controller;import com.jerry.reggie.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.IOException;
import java.util.UUID;/*** ClassName: CommonController* Package: com.jerry.reggie.controller* Description:** @Author jerry_jy* @Create 2023-02-19 17:19* @Version 1.0*//*** 文件上传下载*/
@RestController
@Slf4j
@RequestMapping("/common")
public class CommonController {@Value("${reggie.path}")//这里的value不要导包成了lombok,用${}动态取值private String basePath;/*** 文件上传** @param file* @return*/@PostMapping("/upload")public R<String> uploadFile(MultipartFile file) {//file是临时文件,需要转存到指定位置,否则本次请求完成后临时文件会删除log.info(file.toString());//获取原始文件名String originalFilename = file.getOriginalFilename();//获取原始文件名的后缀名,这里是带点的String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));//使用UUID重新生成文件名,防止文件名称重复造成的文件覆盖String fileName = UUID.randomUUID().toString() + suffix;//创建一个目录对象File dir = new File(basePath);if (!dir.exists()){//目录不存在,创建一个dir.mkdirs();}try {//将临时文件转存到指定位置file.transferTo(new File(basePath + fileName));} catch (IOException e) {throw new RuntimeException(e);}return R.success(fileName);}
}

文件下载代码实现

在这里插入图片描述

/*** 文件下载** @param name* @param response*/
@GetMapping("/download")
public void download(String name, HttpServletResponse response) {try {// 输入流,通过输入流读取文件内容FileInputStream fileInputStream = new FileInputStream(new File(basePath + name));//输出流,通过输出流将文件写回浏览器,在浏览器显示图片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();} catch (Exception e) {throw new RuntimeException(e);}}

7.2、新增菜品

需求分析

在这里插入图片描述

数据模型

在这里插入图片描述

代码开发

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

由于新增菜品涉及到多张表的插入操作,因此需要在Service业务层中单独写一个save方法

DishServiceImpl

package com.jerry.reggie.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jerry.reggie.dto.DishDto;
import com.jerry.reggie.entity.Dish;
import com.jerry.reggie.entity.DishFlavor;
import com.jerry.reggie.mapper.DishFlavorMapper;
import com.jerry.reggie.mapper.DishMapper;
import com.jerry.reggie.service.DishFlavorService;
import com.jerry.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;
import java.util.stream.Collectors;/*** ClassName: DishServiceImpl* Package: com.jerry.reggie.service.impl* Description:** @Author jerry_jy* @Create 2023-02-19 10:53* @Version 1.0*/
@Service
@Slf4j
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {@Autowiredprivate DishFlavorService dishFlavorService;/*** 新增菜品同时保存口味数据* @param dishDto*/@Transactional@Overridepublic void saveWithFlavor(DishDto dishDto) {//保存菜品基本信息到菜品表dishthis.save(dishDto);Long dishId = dishDto.getId();//菜品口味List<DishFlavor> flavors = dishDto.getFlavors();flavors = flavors.stream().map((item) -> {item.setDishId(dishId);return item;}).collect(Collectors.toList());//保存菜品口味到到菜品口味表dish_flavordishFlavorService.saveBatch(flavors);}
}

DishController

package com.jerry.reggie.controller;import com.jerry.reggie.common.R;
import com.jerry.reggie.dto.DishDto;
import com.jerry.reggie.entity.Dish;
import com.jerry.reggie.service.DishFlavorService;
import com.jerry.reggie.service.DishService;
import lombok.extern.java.Log;
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;/*** ClassName: DishController* Package: com.jerry.reggie.controller* Description:** @Author jerry_jy* @Create 2023-02-19 19:11* @Version 1.0*/
@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {@AutowiredDishFlavorService dishFlavorService;@AutowiredDishService dishService;/*** 新增菜品* @param dishDto* @return*/@PostMappingpublic R<String> addMeal(@RequestBody DishDto dishDto){log.info(dishDto.toString());dishService.saveWithFlavor(dishDto);return R.success("保存成功");}
}

7.3、菜品信息分页查询

需求分析

在这里插入图片描述

代码开发

在这里插入图片描述

难点

这里的分页查询涉及到2个对象的拷贝复赋值问题,使用BeanUtils.copyProperties()来完成操作的

把Dish对象赋值给DishDto对象,并设置上categoryName

流式处理的表达式是重点!!!

/*** 菜品信息--分页查询** @param page* @param pageSize* @param name* @return*/
@GetMapping("/page")
public R<Page> page(int page, int pageSize, String name) {//分页构造器Page<Dish> pageInfo = new Page<>(page, pageSize);Page<DishDto> dishDtoPage = new Page<>();//条件构造器LambdaQueryWrapper<Dish> lambdaQueryWrapper = new LambdaQueryWrapper<>();//添加过滤条件lambdaQueryWrapper.like(name != null, Dish::getName, name);//添加过滤条件lambdaQueryWrapper.orderByDesc(Dish::getUpdateTime);dishService.page(pageInfo, lambdaQueryWrapper);//对象拷贝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();//分类idCategory 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);
}

7.4、修改菜品

需求分析

在这里插入图片描述

代码开发

在这里插入图片描述

controller

/**** @param dishDto* @return*/
@PutMapping
public R<String> updateMeal(@RequestBody DishDto dishDto){log.info(dishDto.toString());dishService.updateWithFlavor(dishDto);return R.success("保存菜品成功");
}

DishServiceImpl

/*** 更新菜品信息,同时更新对应的口味信息** @param dishDto*/
@Override
@Transactional
public void updateWithFlavor(DishDto dishDto) {//更新dish表基本信息this.updateById(dishDto);//先清理当前菜品对应的口味信息---dish_flavor表的 delete 操作LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(DishFlavor::getDishId, dishDto.getId());dishFlavorService.remove(lambdaQueryWrapper);//再添加当前提交过来的口味数据--dish_flavor表的 insert 操作List<DishFlavor> flavors = dishDto.getFlavors();flavors = flavors.stream().map((item) -> {item.setDishId(dishDto.getId());return item;}).collect(Collectors.toList());dishFlavorService.saveBatch(flavors);
}

7.5、修改菜品的停/起售状态

DishController

    /*** 修改菜品的 停/启 售状态** @param ids* @return*/@PostMapping("/status/{status}")public R<Dish> status(long ids) {Dish dish = dishService.getById(ids);dishService.setStatus(dish);return R.success(dish);}

DishServiceImpl

/*** 修改菜品的停/启售状态* @param dish*/
@Override
public void setStatus(Dish dish) {if (dish.getStatus()==1){dish.setStatus(0);}else {dish.setStatus(1);}this.updateById(dish);
}

7.6、删除菜品

    /*** 菜品管理--批量删除菜品--跟单个删除一样的,复用同一份代码* @param ids* @return*/@DeleteMappingpublic R<String> delete(Long[] ids){for (Long id : ids) {dishService.delete(id);}return R.success("删除菜品成功!");}

8、套餐管理

8.1、新增套餐

需求分析

在这里插入图片描述

数据模型

在这里插入图片描述

在这里插入图片描述

代码开发

在这里插入图片描述

在这里插入图片描述

DishController

/*** 根据条件来查询对应的菜品数据* @param dish* @return*/
@GetMapping("/list")
public R<List<Dish>> list(Dish dish){//构造查询条件LambdaQueryWrapper<Dish> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());//查询状态为1,启售状态lambdaQueryWrapper.eq(Dish::getStatus,1);//添加排序条件lambdaQueryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);List<Dish> list = dishService.list(lambdaQueryWrapper);return R.success(list);
}

SetmealDishController

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

SetmealServiceImpl

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

8.2、套餐信息分页查询

需求分析

在这里插入图片描述

代码开发

在这里插入图片描述

/*** 套餐管理--套餐信息分页查询* @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> lambdaQueryWrapper = new LambdaQueryWrapper<>();//添加过滤条件lambdaQueryWrapper.like(name != null, Setmeal::getName, name);//添加过滤条件lambdaQueryWrapper.orderByDesc(Setmeal::getUpdateTime);setmealService.page(pageInfo, lambdaQueryWrapper);//对象拷贝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);//分类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);
}

8.3、删除套餐

需求分析

在这里插入图片描述

代码开发

在这里插入图片描述

SetmealController

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

SetmealServiceImpl

/*** 删除套餐,同时输出套餐和菜品关联的数据** @param ids*/
@Override
public void removeWithDish(List<Long> ids) {// 先查询套餐状态,确实是否可以删除// select count(*) from setmeal where id in (1, 2, 3) and status = 1;LambdaQueryWrapper<Setmeal> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.in(Setmeal::getId, ids);lambdaQueryWrapper.eq(Setmeal::getStatus, 1);int count = this.count(lambdaQueryWrapper);if (count > 0) {// 如果不能删除,抛出一个业务异常throw new CustomException("套餐正在售卖中,不能删除");}// 如果可以删除,先删除套餐表中的数据-- setmealthis.removeByIds(ids);//再删除关系表中的数据-- setmeal_dish// delete from setmeal_dish where id in (1, 2, 3);LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.in(SetmealDish::getSetmealId, ids);setmealDishService.remove(queryWrapper);
}

8.4、修改套餐

SetmealController

    /*** 根据id查询套餐信息和对应的套餐内容---回显套餐信息* @param id* @return*/@GetMapping("/{id}")public R<SetmealDto> getMealDtoById(@PathVariable long id){SetmealDto setmealDto = setmealService.getByIdWithSetmeal(id);return R.success(setmealDto);}/*** 修改套餐信息,并保存* @param setmealDto* @return*/@PutMappingpublic R<String> updateSetmeal(@RequestBody SetmealDto setmealDto) {log.info(setmealDto.toString());setmealService.updateWithSetmeal(setmealDto);return R.success("保存菜品成功");}

SetmealService

//根据id查询套餐信息和对应的套餐内容---回显套餐信息
SetmealDto getByIdWithSetmeal(long id);//修改套餐信息,并保存
void updateWithSetmeal(SetmealDto setmealDto);

SetmealServiceImpl

    /*** 根据id查询套餐信息和对应的套餐内容---回显套餐信息** @param id* @return*/@Overridepublic SetmealDto getByIdWithSetmeal(long id) {//查询套餐基本信息,从setmeal表查询Setmeal setMeal = this.getById(id);SetmealDto setmealDto = new SetmealDto();BeanUtils.copyProperties(setMeal, setmealDto);//查询当前套餐对应的套餐信息,从setmeal_dish表中查LambdaQueryWrapper<SetmealDish> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(SetmealDish::getSetmealId, setMeal.getId());List<SetmealDish> setmealDishes = setmealDishService.list(lambdaQueryWrapper);setmealDto.setSetmealDishes(setmealDishes);return setmealDto;}/*** 修改套餐信息,并保存** @param setmealDto*/@Override@Transactionalpublic void updateWithSetmeal(SetmealDto setmealDto) {//更新 setmeal 表基本信息this.updateById(setmealDto);//先清理当前套餐对应的套餐信息--- setmeal_dish 表的 delete 操作LambdaQueryWrapper<SetmealDish> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(SetmealDish::getSetmealId, setmealDto.getId());setmealDishService.remove(lambdaQueryWrapper);//再添加当前提交过来的套餐数据-- setmeal_dish表的 insert 操作List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();setmealDishes = setmealDishes.stream().map((item) -> {item.setSetmealId(setmealDto.getId());return item;}).collect(Collectors.toList());setmealDishService.saveBatch(setmealDishes);}

8.5、停售、启售套餐

SetmealController

/*** 修改套餐的 停/启 售状态* @param ids* @return*/
@PostMapping("/status/{status}")
public R<Setmeal> status(long ids) {Setmeal setmeal = setmealService.getById(ids);setmealService.setStatus(setmeal);return R.success(setmeal);
}

SetmealServiceImpl

/*** 修改套餐的 停/启 售状态* @param setmeal*/
@Override
public void setStatus(Setmeal setmeal) {if (setmeal.getStatus() == 1) {setmeal.setStatus(0);} else {setmeal.setStatus(1);}this.updateById(setmeal);
}

9、前端–手机验证码登录

9.1、短信发送

在这里插入图片描述

阿里云短信服务

https://www.aliyun.com/product/sms?spm=5176.19720258.J_3207526240.37.4cf376f4PiAUnY

在这里插入图片描述

https://dysms.console.aliyun.com/quickstart?spm=5176.25163407.domtextsigncreate-index-1ec3c_58c50_0.1.5097bb6euk5OnF

在这里插入图片描述

设置签名

https://dysms.console.aliyun.com/domestic/text/sign

在这里插入图片描述

切换到【模板管理】标签页

在这里插入图片描述

添加模板详情

在这里插入图片描述

设置AccessKey

在这里插入图片描述

在这里插入图片描述

创建用户

在这里插入图片描述

在这里插入图片描述

自己保存好【AccessKey Secret】

添加权限

在这里插入图片描述

购买短信免费试用包

在这里插入图片描述

代码开发

pom

    <!--阿里云短信服务--><dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-core</artifactId><version>4.5.16</version></dependency><dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-dysmsapi</artifactId><version>2.1.0</version></dependency>

导入utils工具类

在这里插入图片描述

9.2、手机验证码登录

需求分析

在这里插入图片描述

数据模型

在这里插入图片描述

代码开发

在这里插入图片描述

在这里插入图片描述

移动端页面放行的请求

LoginCheckFilter

在这里插入图片描述

//4-2、判断移动端用户登录状态,如果已登录,则直接放行
if (request.getSession().getAttribute("user") != null) {log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("user"));Long userId = (Long) request.getSession().getAttribute("user");BaseContext.setCurrentId(userId);filterChain.doFilter(request, response);return;
}

UserController

package com.jerry.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jerry.reggie.common.R;
import com.jerry.reggie.entity.User;
import com.jerry.reggie.service.UserService;
import com.jerry.reggie.utils.SMSUtils;
import com.jerry.reggie.utils.ValidateCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
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;import javax.servlet.http.HttpSession;
import java.util.Map;/*** ClassName: UserController* Package: com.jerry.reggie.controller* Description:** @Author jerry_jy* @Create 2023-02-21 18:00* @Version 1.0*/
@RestController
@Slf4j
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;/*** 发送手机验证码短信* @param user* @return*/@PostMapping("/sendMsg")public R<String> sendMsg(@RequestBody User user, HttpSession session){//获取手机号String phone = user.getPhone();if (StringUtils.isNotEmpty(phone)){//生成随机的4位验证码String code = ValidateCodeUtils.generateValidateCode(4).toString();log.info("code={}",code);//调用阿里云提供的短信服务API完成短信发送// 没有买短信包,就不发手机短信了
//            SMSUtils.sendMessage("reggie外卖","SMS_270890116",phone,code);// 需要将生成的验证码保存到 session 中session.setAttribute(phone,code);return R.success("手机短信验证码发送成功");}return R.error("短信发送失败");}/*** 移动端用户登录* @param map* @param session* @return*/@PostMapping("/login")public R<User> login(@RequestBody Map map, HttpSession session){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> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(User::getPhone,phone);User user = userService.getOne(lambdaQueryWrapper);if (user==null){// 判断当前手机号是否为新用户,如果是新用户就能自动完成注册user= new User();user.setPhone(phone);user.setStatus(1);userService.save(user);}session.setAttribute("user", user.getId());return R.success(user);}return R.error("登录失败");}
}

10、前端–导入用户地址簿

需求分析

在这里插入图片描述

数据模型

在这里插入图片描述

代码开发

在这里插入图片描述

AddressBookController

package com.jerry.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.jerry.reggie.common.BaseContext;
import com.jerry.reggie.common.R;
import com.jerry.reggie.entity.AddressBook;
import com.jerry.reggie.service.AddressBookService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;/*** ClassName: AddressBookController* Package: com.jerry.reggie.controller* Description:** @Author jerry_jy* @Create 2023-02-21 20:42* @Version 1.0*//*** 地址簿管理*/
@Slf4j
@RestController
@RequestMapping("/addressBook")
public class AddressBookController {@Autowiredprivate AddressBookService addressBookService;/*** 新增*/@PostMappingpublic R<AddressBook> save(@RequestBody AddressBook addressBook) {addressBook.setUserId(BaseContext.getCurrentId());log.info("addressBook:{}", addressBook);addressBookService.save(addressBook);return R.success(addressBook);}/*** 设置默认地址*/@PutMapping("default")public R<AddressBook> setDefault(@RequestBody AddressBook addressBook) {log.info("addressBook:{}", addressBook);LambdaUpdateWrapper<AddressBook> wrapper = new LambdaUpdateWrapper<>();wrapper.eq(AddressBook::getUserId, BaseContext.getCurrentId());wrapper.set(AddressBook::getIsDefault, 0);//SQL:update address_book set is_default = 0 where user_id = ?addressBookService.update(wrapper);addressBook.setIsDefault(1);//SQL:update address_book set is_default = 1 where id = ?addressBookService.updateById(addressBook);return R.success(addressBook);}/*** 根据id查询地址*/@GetMapping("/{id}")public R get(@PathVariable Long id) {AddressBook addressBook = addressBookService.getById(id);if (addressBook != null) {return R.success(addressBook);} else {return R.error("没有找到该对象");}}/*** 查询默认地址*/@GetMapping("default")public R<AddressBook> getDefault() {LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(AddressBook::getUserId, BaseContext.getCurrentId());queryWrapper.eq(AddressBook::getIsDefault, 1);//SQL:select * from address_book where user_id = ? and is_default = 1AddressBook addressBook = addressBookService.getOne(queryWrapper);if (null == addressBook) {return R.error("没有找到该对象");} else {return R.success(addressBook);}}/*** 查询指定用户的全部地址*/@GetMapping("/list")public R<List<AddressBook>> list(AddressBook addressBook) {addressBook.setUserId(BaseContext.getCurrentId());log.info("addressBook:{}", addressBook);//条件构造器LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(null != addressBook.getUserId(), AddressBook::getUserId, addressBook.getUserId());queryWrapper.orderByDesc(AddressBook::getUpdateTime);//SQL:select * from address_book where user_id = ? order by update_time descreturn R.success(addressBookService.list(queryWrapper));}
}

11、前端–菜品展示

需求分析

在这里插入图片描述

代码开发

在这里插入图片描述

展示flavor口味信息

// 前端需要展示flavor口味信息
@GetMapping("/list")
public R<List<DishDto>> list(Dish dish) {//构造查询条件LambdaQueryWrapper<Dish> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId());//查询状态为1,启售状态lambdaQueryWrapper.eq(Dish::getStatus, 1);//添加排序条件lambdaQueryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);List<Dish> list = dishService.list(lambdaQueryWrapper);List<DishDto> dishDtoList = list.stream().map((item) -> {DishDto dishDto = new DishDto();//对象拷贝BeanUtils.copyProperties(item, dishDto);Long categoryId = item.getCategoryId();//分类idCategory category = categoryService.getById(categoryId);//分类对象if (category != null) {String categoryName = category.getName();dishDto.setCategoryName(categoryName);}//当前菜品idLong dishId = item.getId();LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(DishFlavor::getDishId,dishId);List<DishFlavor> dishFlavorList = dishFlavorService.list(queryWrapper);dishDto.setFlavors(dishFlavorList);return dishDto;}).collect(Collectors.toList());return R.success(dishDtoList);
}

套餐信息展示

/*** 根据条件查询套餐数据** @param setmeal* @return*/
@GetMapping("/list")
public R<List<Setmeal>> list(Setmeal setmeal) {//构造查询条件LambdaQueryWrapper<Setmeal> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(setmeal.getCategoryId() != null, Setmeal::getCategoryId, setmeal.getCategoryId());//查询状态为1,启售状态lambdaQueryWrapper.eq(setmeal.getStatus() != null, Setmeal::getStatus, setmeal.getStatus());//添加排序条件lambdaQueryWrapper.orderByDesc(Setmeal::getUpdateTime);List<Setmeal> list = setmealService.list(lambdaQueryWrapper);return R.success(list);
}

12、前端–购物车

需求分析

在这里插入图片描述

数据模型

在这里插入图片描述

代码开发

在这里插入图片描述

在这里插入图片描述

购物车需要实现查看/增加/减少/清空商品

package com.jerry.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jerry.reggie.common.BaseContext;
import com.jerry.reggie.common.R;
import com.jerry.reggie.entity.ShoppingCart;
import com.jerry.reggie.service.ShoppingCartService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.time.LocalDateTime;
import java.util.List;/*** ClassName: ShoppingCartController* Package: com.jerry.reggie.controller* Description:** @Author jerry_jy* @Create 2023-02-22 10:14* @Version 1.0*/
@RestController
@RequestMapping("/shoppingCart")
@Slf4j
public class ShoppingCartController {@Autowiredprivate ShoppingCartService shoppingCartService;/*** 添加购物车** @param shoppingCart* @return*/@PostMapping("/add")public R<ShoppingCart> add(@RequestBody ShoppingCart shoppingCart) {log.info("购物车数据封装,{}", shoppingCart.toString());// 设置用户id,指定当前是哪个用户的购物车数据Long currentId = BaseContext.getCurrentId();shoppingCart.setUserId(currentId);Long dishId = shoppingCart.getDishId();LambdaQueryWrapper<ShoppingCart> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(ShoppingCart::getUserId, shoppingCart.getUserId());if (dishId != null) {// 添加到购物车的是菜品lambdaQueryWrapper.eq(ShoppingCart::getDishId, dishId);} else {// 添加到购物车的是套餐lambdaQueryWrapper.eq(ShoppingCart::getSetmealId, shoppingCart.getSetmealId());}// 查询当前菜品或套餐是否在购物车中,ShoppingCart cart = shoppingCartService.getOne(lambdaQueryWrapper);if (cart != null) {//如果已经存在,就在原来数量基础上加一Integer number = cart.getNumber();cart.setNumber(number + 1);shoppingCartService.updateById(cart);} else {// 如果不存在,则x添加到购物车,数量默认就是 1shoppingCart.setNumber(1);shoppingCart.setCreateTime(LocalDateTime.now());shoppingCartService.save(shoppingCart);cart = shoppingCart;}return R.success(cart);}/*** 减少购物车的菜品** @return*/@PostMapping("/sub")public R<ShoppingCart> sub(@RequestBody ShoppingCart shoppingCart) {log.info("购物车数据封装,{}", shoppingCart.toString());LambdaQueryWrapper<ShoppingCart> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(ShoppingCart::getUserId, BaseContext.getCurrentId());if (shoppingCart.getDishId() != null) {// 减少到购物车的是菜品lambdaQueryWrapper.eq(ShoppingCart::getDishId, shoppingCart.getDishId());} else {// 减少到购物车的是套餐lambdaQueryWrapper.eq(ShoppingCart::getSetmealId, shoppingCart.getSetmealId());}// 查询当前菜品或套餐是否在购物车中,ShoppingCart cart = shoppingCartService.getOne(lambdaQueryWrapper);//如果已经存在并且数量 > 1,就在原来数量基础上 - 1if ((cart.getNumber() > 1)) {Integer number = cart.getNumber();cart.setNumber(number - 1);shoppingCartService.updateById(cart);} else {//移除改菜品或套餐shoppingCartService.remove(lambdaQueryWrapper);}return R.success(cart);}/*** 清空购物车** @return*/@DeleteMapping("/clean")public R<String> clean() {LambdaQueryWrapper<ShoppingCart> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(ShoppingCart::getUserId, BaseContext.getCurrentId());shoppingCartService.remove(lambdaQueryWrapper);return R.success("清空购物车成功");}/*** 查看购物车** @return*/@GetMapping("/list")public R<List<ShoppingCart>> list() {log.info("查看购物车...");LambdaQueryWrapper<ShoppingCart> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(ShoppingCart::getUserId, BaseContext.getCurrentId());lambdaQueryWrapper.orderByAsc(ShoppingCart::getCreateTime);List<ShoppingCart> list = shoppingCartService.list(lambdaQueryWrapper);return R.success(list);}
}

13、前端–用户下单

需求分析

在这里插入图片描述

数据模型

在这里插入图片描述

在这里插入图片描述

代码开发

在这里插入图片描述

在这里插入图片描述

OrderController

package com.jerry.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jerry.reggie.common.R;
import com.jerry.reggie.entity.Orders;
import com.jerry.reggie.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;/*** ClassName: OrderController* Package: com.jerry.reggie.controller* Description:** @Author jerry_jy* @Create 2023-02-22 13:53* @Version 1.0*/@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {@Autowiredprivate OrderService orderService;/*** 用户下单* @param orders* @return*/@PostMapping("/submit")public R<String> submit(@RequestBody Orders orders){log.info("订单数据:{}",orders);orderService.submit(orders);return R.success("下单成功");}/*** 订单查询* @param page* @param pageSize* @return*/@GetMapping("/userPage")public R<Page> userPage(int page, int pageSize){//分页构造器Page<Orders> pageInfo = new Page<>();//条件构造器LambdaQueryWrapper<Orders> lambdaQueryWrapper = new LambdaQueryWrapper<>();//添加排序条件lambdaQueryWrapper.orderByDesc(Orders::getOrderTime);orderService.page(pageInfo, lambdaQueryWrapper);return R.success(pageInfo);}
}

OrderService

package com.jerry.reggie.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.jerry.reggie.entity.Orders;/*** ClassName: OrderService* Package: com.jerry.reggie.service* Description:** @Author jerry_jy* @Create 2023-02-22 13:52* @Version 1.0*/
public interface OrderService extends IService<Orders> {//用户下单void submit(Orders orders);
}

OrderServiceImpl

package com.jerry.reggie.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jerry.reggie.common.BaseContext;
import com.jerry.reggie.common.CustomException;
import com.jerry.reggie.entity.*;
import com.jerry.reggie.mapper.OrderMapper;
import com.jerry.reggie.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;/*** ClassName: OrderServiceImpl* Package: com.jerry.reggie.service.impl* Description:** @Author jerry_jy* @Create 2023-02-22 13:52* @Version 1.0*/@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService {@Autowiredprivate ShoppingCartService shoppingCartService;@Autowiredprivate UserService userService;@Autowiredprivate AddressBookService addressBookService;@Autowiredprivate OrderDetailService orderDetailService;/*** 用户下单* @param orders*/@Transactional@Overridepublic void submit(Orders orders) {// 获取用户idLong userId = BaseContext.getCurrentId();// 查询当前用户购物车的数据LambdaQueryWrapper<ShoppingCart> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(ShoppingCart::getUserId,userId);List<ShoppingCart> shoppingCartList = shoppingCartService.list(lambdaQueryWrapper);if (shoppingCartList == null || shoppingCartList.size()==0){throw new CustomException("购物车为空,不能下单");}// 查询用户数据User user = userService.getById(userId);// 查询地址数据Long addressBookId = orders.getAddressBookId();AddressBook addressBook = addressBookService.getById(addressBookId);if (addressBook == null){throw new CustomException("用户地址信息有误,不能下单");}long orderId = IdWorker.getId();//生成订单号AtomicInteger amount = new AtomicInteger(0);List<OrderDetail> orderDetails= shoppingCartList.stream().map((item)->{OrderDetail orderDetail = new OrderDetail();orderDetail.setOrderId(orderId);orderDetail.setNumber(item.getNumber());orderDetail.setDishFlavor(item.getDishFlavor());orderDetail.setDishId(item.getDishId());orderDetail.setSetmealId(item.getSetmealId());orderDetail.setName(item.getName());orderDetail.setImage(item.getImage());orderDetail.setAmount(item.getAmount());amount.addAndGet(item.getAmount().multiply(new BigDecimal(item.getNumber())).intValue());return orderDetail;}).collect(Collectors.toList());orders.setId(orderId);orders.setOrderTime(LocalDateTime.now());orders.setCheckoutTime(LocalDateTime.now());orders.setStatus(2);orders.setAmount(new BigDecimal(amount.get()));//总金额orders.setUserId(userId);orders.setNumber(String.valueOf(orderId));orders.setUserName(user.getName());orders.setConsignee(addressBook.getConsignee());orders.setPhone(addressBook.getPhone());orders.setAddress((addressBook.getProvinceName() == null ? "" : addressBook.getProvinceName())+ (addressBook.getCityName() == null ? "" : addressBook.getCityName())+ (addressBook.getDistrictName() == null ? "" : addressBook.getDistrictName())+ (addressBook.getDetail() == null ? "" : addressBook.getDetail()));// 向订单表插入,一条数据this.save(orders);// 向订单明细表插入,多条数据orderDetailService.saveBatch(orderDetails);//清空购物车数据shoppingCartService.remove(lambdaQueryWrapper);}
}

14、代码托管

Git版本管理

在这里插入图片描述

Gitee

https://gitee.com/jinyang-jy/reggie.git

Github

https://github.com/Jerry-jy/reggie.git

项目所需资料

链接:https://pan.baidu.com/s/182tTb1rmGkTCbq9aXrbjMg?pwd=2022
提取码:2022

相关文章:

基于SpringBoot的外卖项目(详细开发过程)

基于SpringBootMyBatisPlus的外卖项目1、软件开发整体介绍软件开发流程角色分工2、外卖项目介绍项目介绍产品展示后台系统管理移动端技术选型功能结构角色3、开发环境的搭建开发环境说明建库建表Maven项目搭建项目的目录结构pom.xmlapplication.ymlReggieApplication启动类配置…...

ChatGPT 研发传言席卷互联网公司,这会是一门好生意吗?

ChatGPT&#xff08;也称GPT-3&#xff09;是一种基于人工智能的自然语言生成模型&#xff0c;由OpenAI团队开发。它是GPT系列模型的最新版本&#xff0c;于2020年6月发布。ChatGPT的由来GPT-1是在2018年发布的第一个版本&#xff0c;使用了12亿个参数。随后&#xff0c;GPT-2在…...

获取servlet转发和响应重定向的方式是什么?

&#xff08;1&#xff09; 重定向和转发的区别 1&#xff09;重定向是浏览器发送请求并受到响应以后再次向一个新地址发请求&#xff1b;转发是服务器受到请求后为了完成响应转到一个新的地址。 2&#xff09;重定向中有两次请求对象&#xff0c;不共享数据&#xff1b;转发…...

jvm知识点

jvm面试总结 类加载机制? 如何把类加载到jvm中 ? 装载–>链接–>初始化–>使用–>卸载 装载: ClassFile–>字节流–>类加载器将字节流所代表的静态结构转化为方法区的运行时数据结构在我们的堆中生成一个代表这个类的java.lang.Class对象 链接: 验证–…...

MoveIT Noetic控制真实机械臂

文章目录 环境概述配置修改编写Action Server执行问题故障解决参考接前几篇: ROS MoveIT1(Noetic)安装总结 Solidworks导出为URDF用于MoveIT总结(带prismatic) MoveIT1 Assistant 总结 MoveIT Rviz和Gazebo联合仿真 环境 Ubuntu20.04;ROS1 Noetic;VMware...

如何快速入门编程

最近回答了很多小伙伴的问题&#xff0c;讲到如何快速入门编程&#xff1f;如何更好地学习视觉编程&#xff1f;如何提高编程技能&#xff1f;下面就和你聊聊&#xff0c;要做到这些&#xff0c;应该从哪些方面入手&#xff1f;询问他人我问过工程师们这些最基础的问题&#xf…...

java的反射Reflect

文章目录定义classClass获取一个类的类对象反射的具体步骤1.加载类类API2.实例化3.获取1)获取类中方法2)获取构造方法3)获取当前类的属性4.方法调用应用1.遍历对象属性&#xff0c;进行赋值定义 反射是操作其属性和方法从编码期决定转为在运行期决定 编码期决定&#xff1a;创…...

常用设计模式总结

复习到设计模式的时候写的一些demo代码 回头可以看看 单例的几种比较简单就没写了&#xff0c;专栏有 目录 观察者&#xff08;发布--订阅模式&#xff09;模式&#xff0c;多个对象依赖于一个对象&#xff0c;或者多对多 工厂模式&#xff1a;主要是封装了对象的创建&…...

【算法基础】一维前缀和 + 二维前缀和

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;【C/C】算法 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵 希望大佬指点一二 如果文章对你有…...

Kafka消费分组和分区分配策略

Kafka消费分组&#xff0c;消息消费原理 同一个消费组里的消费者不能消费同一个分区&#xff0c;不同消费组的消费组可以消费同一个分区 &#xff08;即同一个消费组里面的消费者只能在一个分区中&#xff09; Kafka分区分配策略 问题 用过 Kafka 的同学用过都知道&#xf…...

犹太教、基督教、伊斯兰教的区别与联系

一、犹太教、基督教、伊斯兰教的简明关系图二、犹太教、基督教、伊斯兰教的主要区别注&#xff1a;弥赛亚&#xff08;希伯莱语&#xff09;就是基督&#xff08;希腊语&#xff09;&#xff0c;意思是“救世主”。注&#xff1a;伊斯兰教的观点是&#xff1a;穆罕默德不是伊斯…...

华为OD机试 - 打印文件(Python) | 机试题+算法思路+考点+代码解析 【2023】

打印文件 题目 有 5 台打印机打印文件,每台打印机有自己的待打印队列。 因为打印的文件内容有轻重缓急之分,所以队列中的文件有1~10不同的优先级,其中数字越大优先级越高。 打印机会从自己的待打印队列中选择优先级最高的文件来打印。 如果存在两个优先级一样的文件,则选…...

网络工程师必备知识点

作为网络工程师&#xff0c;您将负责设计、部署和维护计算机网络系统。这包括构建、配置和管理网络设备&#xff0c;如交换机、路由器、防火墙等&#xff0c;并确保网络系统能够高效地运行。您需要了解计算机网络的各个层次、协议、标准和技术&#xff0c;包括TCP/IP、DNS、HTT…...

数据在内存中的存储【下篇】

文章目录⚙️3.浮点型在内存中的存储&#x1f529;3.1.一个例子&#x1f529;3.2.浮点数的存储规则&#x1f529;3.3.例题解析⚙️3.浮点型在内存中的存储 &#x1f529;3.1.一个例子 &#x1f534;浮点数存储的例子&#xff1a;&#x1f447; int main() {int n 9;float* …...

前端开发项目规范写法介绍

1. 基本原则 结构、样式、行为分离 尽量确保文档和模板只包含 HTML 结构,样式都放到样式表里,行为都放到脚本里。 缩进 统一两个空格缩进(总之缩进统一即可),不要使用 Tab 或者 Tab、空格混搭。 文件编码 使用不带 BOM 的 UTF-8 编码。 在 HTML中指定编码 <meta c…...

百万医疗险是什么

一、百万医疗险是什么 从名字可以看出&#xff0c;这是一款医疗险。因为保额高&#xff0c;最高能报销百万&#xff0c;所以叫百万医疗险。 二、百万医疗险有什么用 可以报销被保险人因意外伤害和疾病导致的医疗费用 三、如何挑选 虽然高达几百万的保额&#xff0c;但保额却并非…...

矩阵中的路径 AcWing (JAVA)

请设计一个函数&#xff0c;用来判断在一个矩阵中是否存在一条路径包含的字符按访问顺序连在一起恰好为给定字符串。 路径可以从矩阵中的任意一个格子开始&#xff0c;每一步可以在矩阵中向左&#xff0c;向右&#xff0c;向上&#xff0c;向下移动一个格子。 如果一条路径经过…...

使用终端工具给你的电脑发送弹窗提醒

大家好&#xff0c;我是良许。 现在人手一部智能手机&#xff0c;这些智能手机都有个非常实用的功能&#xff0c;那就是弹窗提醒。当我们收到短信&#xff0c;或者微信信息时&#xff0c;手机就会弹窗显示信息的大致内容。有了这个功能你就不会错过重要信息了。 电脑上也有类…...

SpringCloud Alibaba 之Nacos集群部署-高可用保证

文章目录Nacos集群部署Linux部署docker部署&#xff08;参考待验证&#xff09;Nacos 集群的工作原理Nacos 集群中 Leader 节点是如何产生的Nacos 节点间的数据同步过程官方推荐用户把所有服务列表放到一个vip下面&#xff0c;然后挂到一个域名下面。http://nacos.com:port/ope…...

Scala集合详解(第七章:集合、数组、列表、set集合、map集合、元组、队列、并行)(尚硅谷笔记)

集合第七章:集合7.1 集合简介7.1.1 不可变集合继承图7.1.2 可变集合继承图7.2 数组7.2.1 不可变数组7.2.2 可变数组7.2.3 不可变数组与可变数组的转换7.2.4 多维数组7.3 列表 List7.3.1 不可变 List7.3.2 可变 ListBuffer7.4 Set 集合7.4.1 不可变 Set7.4.2 可变 mutable.Set7.…...

定了:Python3.7,今年停止更新~

大家好&#xff0c;这里是程序员晚枫。 今天给大家分享一个来自Python官网的重要消息&#xff1a;Python3.7马上就要停止维护了&#xff0c;请不要使用了&#xff01; 官网链接&#xff1a;https://devguide.python.org/versions/ 停更的后果是什么&#xff1f; 周末翻阅Py…...

C# 业务单据号生成器(定义规则、获取编号、流水号)

系列文章 C#底层库–数据库访问帮助类&#xff08;MySQL版&#xff09; 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/126886379 C#底层库–JSON帮助类_详细&#xff08;序列化、反序列化、list、datatable&#xff09; 本文链接&#xff1a;htt…...

Java的dump文件分析及JProfiler使用

Java的dump文件分析及JProfiler使用 1 dump文件介绍 从软件开发的角度上&#xff0c;dump文件就是当程序产生异常时&#xff0c;用来记录当时的程序状态信息&#xff08;例如堆栈的状态&#xff09;,用于程序开发定位问题。 idea配置发生OOM的时候指定路径生成dump文件 # 指定…...

sympy高斯光束模型

文章目录Gauss模型sympy封装实战sympy.phisics.optics.gaussopt集成了高斯光学中的常见对象&#xff0c;包括光线和光学元件等&#xff0c;有了这些东西&#xff0c;就可以制作一个光学仿真系统。Gauss模型 高斯光束的基本模型为 E(r,z)E0ω0ω(z)exp⁡[−r2ω2(z)]exp⁡[−ik…...

Cloudflared 内网穿透 使用记录

Cloudflared 内网穿透前提创建cloudflared tunnel我使用的服务前提 你必须要有一个域名&#xff0c;并且可以改域名的dns解析服务商到cloudflare 1.登录到cloudflare后台&#xff0c;点击添加站点 2.输入自己的域名&#xff0c;下一步选择免费套餐 3.他会搜索这个域名下已有…...

柴油发电机组的调压板

1 概述 柴油发电机组的调压板是一种用于控制发电机输出电压的装置。它通常由一块电子电路板和一个电子电路板上的电位器组成。 当发电机运行时&#xff0c;它会产生电压&#xff0c;然后通过调压板中的电路进行控制。调压板中的电路会检测输出电压的大小&#xff0c;并通过电…...

【MySQL】表操作和库操作

文章目录概念库操作1.创建数据库2.删除数据库3.选择数据库4.显示数据库列表表操作1.创建数据表CREATE2.删除数据表DROP3.插入数据INSERT4.更新数据UPDATE5.修改数据ALTER6.查询数据SELECT7.WHERE子句8.ORDER BY子句9.LIMIT子句10.GROUP BY子句11.HAVING子句使用注意事项概念 M…...

拓扑排序的思想?用代码怎么实现

目录 一、拓扑排序的思想 二、代码实现&#xff08;C&#xff09; 代码思想 核心代码 完整代码 一、拓扑排序的思想 以西红柿炒鸡蛋这道菜为例&#xff0c;其中的做饭流程为&#xff1a; 中间2 6 3 7 4的顺序都可以任意调换&#xff0c;但1和5必须在最前面&#xff0c;这是…...

【Git】码云

目录 5、 Git 团队协作机制 5.1 团队内协作 5.2 跨团队协作 6、 Gitee码云 操作 6.1 创建远程仓库 6.2 远程仓库操作 6.3 SSH 免密登录 5、 Git 团队协作机制 5.1 团队内协作 5.2 跨团队协作 6、 Gitee码云 操作 码云网址&#xff1a; https://githee.com/ 账号验证…...

数据结构与算法(三):栈与队列

上一篇《数据结构与算法&#xff08;二&#xff09;&#xff1a;线性表》中介绍了数据结构中线性表的两种不同实现——顺序表与链表。这一篇主要介绍线性表中比较特殊的两种数据结构——栈与队列。首先必须明确一点&#xff0c;栈和队列都是线性表&#xff0c;它们中的元素都具…...