基于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/>   </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: 8080spring:  application:    # 应用名称,可选项    name: reggie  datasource:    druid:      driver-class-name: com.mysql.cj.jdbc.Driver      url: jdbc:mysql://localhost:3306/reggie" />

4、登录功能

4.1、后台登录功能

需求分析

代码编写

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

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

R.java

package com.jerry.reggie.common;import lombok.Data;import java.util.HashMap;import java.util.Map;/** * 通用返回结果,服务器端响应的数据最终都会封装成此对象 * @param  */@Datapublic 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;/** * 员工实体类 */@Datapublic 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 */@Mapperpublic 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 */@Servicepublic 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 {    @Autowired    private 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 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中的用户id    request.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();    @Override    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {        HttpServletRequest request = (HttpServletRequest) servletRequest;        HttpServletResponse response = (HttpServletResponse) servletResponse;        //1、获取本次请求的URI        String uri = request.getRequestURI(); //   backend/index.html        log.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 */@PostMappingpublic 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());    //获得当前登录对象的id    Long 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数据时就写@Slf4jpublic 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的分页插件 */@Configurationpublic class MyBatisPlusConfig {    @Bean    public 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 */@PutMappingpublic 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 */@Overrideprotected void extendMessageConverters(List<HttpMessageConverter<" />

代码编写

/** * 根据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 */@Servicepublic class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {    @Autowired    private DishService dishService;    @Autowired    private SetmealService setmealService;    /**     * 根据id删除分类,删除之前需要进行判断     * @param id     */    @Override    public 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     */    @DeleteMapping    public R<String> delete(Long id){        log.info("删除分类:{}",id);//        categoryService.removeById(id);        categoryService.remove(id);        return R.success("分类信息删除成功");    }

6.3、修改分类

需求分析

代码编写

/** * 根据id修改分类信息 * @param category * @return */@PutMappingpublic 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@Slf4jpublic class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {    @Autowired    private DishFlavorService dishFlavorService;    /**     * 新增菜品同时保存口味数据     * @param dishDto     */    @Transactional    @Override    public void saveWithFlavor(DishDto dishDto) {        //保存菜品基本信息到菜品表dish        this.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_flavor        dishFlavorService.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 {    @Autowired    DishFlavorService dishFlavorService;    @Autowired    DishService dishService;    /**     * 新增菜品     * @param dishDto     * @return     */    @PostMapping    public 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();//分类id        Category category = categoryService.getById(categoryId);//分类对象        if (category!=null){            String categoryName = category.getName();            dishDto.setCategoryName(categoryName);        }                return dishDto;    }).collect(Collectors.toList());    dishDtoPage.setRecords(list);    return R.success(dishDtoPage);}

7.4、修改菜品

需求分析

代码开发

controller

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

DishServiceImpl

/** * 更新菜品信息,同时更新对应的口味信息 * * @param dishDto */@Override@Transactionalpublic 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 */@Overridepublic void setStatus(Dish dish) {    if (dish.getStatus()==1){        dish.setStatus(0);    }else {        dish.setStatus(1);    }    this.updateById(dish);}

7.6、删除菜品

    /**     * 菜品管理--批量删除菜品--跟单个删除一样的,复用同一份代码     * @param ids     * @return     */    @DeleteMapping    public 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 */@PostMappingpublic R<String> save(@RequestBody SetmealDto setmealDto){    log.info("套餐信息:{}",setmealDto.toString());    setmealService.saveWithDish(setmealDto);    return R.success("新增套餐成功");}

SetmealServiceImpl

/** * 新增套餐,同时需要保存套餐和菜品的关联关系 * @param setmealDto */@Override@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);}

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);        //分类id        Long categoryId = item.getCategoryId();        //根据分类id查询对象        Category category = categoryService.getById(categoryId);        if (category != null) {            //获取分类名称            String categoryName = category.getName();            setmealDto.setCategoryName(categoryName);        }        return setmealDto;    }).collect(Collectors.toList());    dtoPage.setRecords(list);    return R.success(dtoPage);}

8.3、删除套餐

需求分析

代码开发

SetmealController

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

SetmealServiceImpl

/** * 删除套餐,同时输出套餐和菜品关联的数据 * * @param ids */@Overridepublic 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("套餐正在售卖中,不能删除");    }    // 如果可以删除,先删除套餐表中的数据-- setmeal    this.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     */    @PutMapping    public 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     */    @Override    public 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    @Transactional    public 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 */@Overridepublic void setStatus(Setmeal setmeal) {    if (setmeal.getStatus() == 1) {        setmeal.setStatus(0);    } else {        setmeal.setStatus(1);    }    this.updateById(setmeal);}

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

9.1、短信发送

阿里云短信服务

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 {    @Autowired    private 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 {    @Autowired    private AddressBookService addressBookService;    /**     * 新增     */    @PostMapping    public 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 = " />

代码开发

展示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();//分类id        Category category = categoryService.getById(categoryId);//分类对象        if (category != null) {            String categoryName = category.getName();            dishDto.setCategoryName(categoryName);        }        //当前菜品id        Long 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")@Slf4jpublic class ShoppingCartController {    @Autowired    private 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添加到购物车,数量默认就是 1            shoppingCart.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,就在原来数量基础上 - 1        if ((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 {    @Autowired    private 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 */@Servicepublic class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService { @Autowired private ShoppingCartService shoppingCartService; @Autowired private UserService userService; @Autowired private AddressBookService addressBookService; @Autowired private OrderDetailService orderDetailService; /**     * 用户下单     * @param orders     */ @Transactional @Override public void submit(Orders orders) { // 获取用户id Long 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 " />

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