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

news/2024/11/24 20:56:39/

基于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


http://www.ppmy.cn/news/27276.html

相关文章

whistle+SwitchyOmega配置代理解决白名单跨越

文章目录whistleSwitchyOmega配置代理什么是whistle什么是SwitchyOmega示例&#xff1a;作用为什么不直接使用SwitchyOmega代理whistleSwitchyOmega配置代理 什么是whistle whistle主要用于查看、修改HTTP、HTTPS、Websocket的请求、响应&#xff0c;也可以作为HTTP代理服务器…

ideal创建maven项目

前置工作本机安装mavenIdea 设置使用本机maven 工具Settings--->Maven开始创建maven项目创建maven项目&#xff0c;勾选通过模板创建&#xff0c;选择 maven-archetype-webapp 模板GroupId: 公司名倒序ArtifactId: 项目名设置本地maven仓库配置项目文件显示名&#xff0c;和…

C语言——柔性数组

目录0. 前言1. 思维导图2. 柔性数组的特点3. 柔性数组的使用4. 柔性数组的优势5. 结语0. 前言 柔性数组是在C99标准时引入&#xff1a; 结构中的最后一个元素允许是未知大小的数组&#xff0c;这就叫柔性数组成员。 代码示例&#xff1a; typedef struct flexible_arr {int a…

FPGA纯vhdl实现MIPI CSI2 RX视频解码输出,OV13850采集,提供工程源码和技术支持

目录1、前言2、Xilinx官方主推的MIPI解码方案3、纯Vhdl方案解码MIPI4、vivado工程介绍5、上板调试验证6、福利&#xff1a;工程代码的获取1、前言 FPGA图像采集领域目前协议最复杂、技术难度最高的应该就是MIPI协议了&#xff0c;MIPI解码难度之高&#xff0c;令无数英雄竞折腰…

Python的PyQt框架的使用-资源文件夹的使用

Python的PyQt框架的使用-资源文件夹的使用一、前言二、Qt Designer加载资源文件三、资源文件的转换一、前言 个人主页: ζ小菜鸡大家好我是ζ小菜鸡&#xff0c;小伙伴们&#xff0c;让我们一起来学习Python的PyQt框架的使用。如果文章对你有帮助、欢迎关注、点赞、收藏(一键三…

Wgcloud安装和使用(性能监控)

一、Wgcloud说明 官网&#xff1a;https://www.wgstart.com/ WGCLOUD支持主机各种指标监测&#xff08;cpu使用率&#xff0c;cpu温度&#xff0c;内存使用率&#xff0c;磁盘容量&#xff0c;磁盘IO&#xff0c;硬盘SMART健康状态&#xff0c;系统负载&#xff0c;连接数量&…

设计模式-行为型模式:策略模式

目录 1、简介 2、组成部分 3、优缺点 4、使用场景 5、代码实现 1、简介 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一系列算法&#xff0c;将每个算法封装起来&#xff0c;使它们可以相互替换&#xff0c;而且算法的变化…

论文投稿指南——中文核心期刊推荐(法律 2)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…