IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 单体项目-瑞吉外卖 -> 正文阅读

[Java知识库]单体项目-瑞吉外卖

作者:token annotation punctuation

员工管理

Day01

数据库建立

数据库文件配置,创建数据库 Reggie,新建 Query

/*
Navicat MySQL Data Transfer

Source Server         : localhost
Source Server Version : 50728
Source Host           : localhost:3306
Source Database       : reggie

Target Server Type    : MYSQL
Target Server Version : 50728
File Encoding         : 65001

Date: 2021-07-23 10:41:41
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for address_book
-- ----------------------------
DROP TABLE IF EXISTS `address_book`;
CREATE TABLE `address_book` (
  `id` bigint(20) NOT NULL COMMENT '主键',
  `user_id` bigint(20) NOT NULL COMMENT '用户id',
  `consignee` varchar(50) COLLATE utf8_bin NOT NULL COMMENT '收货人',
  `sex` tinyint(4) NOT NULL COMMENT '性别 0 女 1 男',
  `phone` varchar(11) COLLATE utf8_bin NOT NULL COMMENT '手机号',
  `province_code` varchar(12) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '省级区划编号',
  `province_name` varchar(32) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '省级名称',
  `city_code` varchar(12) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '市级区划编号',
  `city_name` varchar(32) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '市级名称',
  `district_code` varchar(12) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '区级区划编号',
  `district_name` varchar(32) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '区级名称',
  `detail` varchar(200) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '详细地址',
  `label` varchar(100) CHARACTER SET utf8mb4 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(20) NOT NULL COMMENT '创建人',
  `update_user` bigint(20) NOT NULL COMMENT '修改人',
  `is_deleted` int(11) NOT NULL DEFAULT '0' COMMENT '是否删除',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='地址管理';

-- ----------------------------
-- Records of address_book
-- ----------------------------
INSERT INTO `address_book` 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');
INSERT INTO `address_book` VALUES ('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');

-- ----------------------------
-- Table structure for category
-- ----------------------------
DROP TABLE IF EXISTS `category`;
CREATE TABLE `category` (
  `id` bigint(20) NOT NULL COMMENT '主键',
  `type` int(11) DEFAULT NULL COMMENT '类型   1 菜品分类 2 套餐分类',
  `name` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '分类名称',
  `sort` int(11) NOT NULL DEFAULT '0' COMMENT '顺序',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `update_time` datetime NOT NULL COMMENT '更新时间',
  `create_user` bigint(20) NOT NULL COMMENT '创建人',
  `update_user` bigint(20) NOT NULL COMMENT '修改人',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `idx_category_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='菜品及套餐分类';

-- ----------------------------
-- Records of category
-- ----------------------------
INSERT INTO `category` VALUES ('1397844263642378242', '1', '湘菜', '1', '2021-05-27 09:16:58', '2021-07-15 20:25:23', '1', '1');
INSERT INTO `category` VALUES ('1397844303408574465', '1', '川菜', '2', '2021-05-27 09:17:07', '2021-06-02 14:27:22', '1', '1');
INSERT INTO `category` VALUES ('1397844391040167938', '1', '粤菜', '3', '2021-05-27 09:17:28', '2021-07-09 14:37:13', '1', '1');
INSERT INTO `category` VALUES ('1413341197421846529', '1', '饮品', '11', '2021-07-09 11:36:15', '2021-07-09 14:39:15', '1', '1');
INSERT INTO `category` VALUES ('1413342269393674242', '2', '商务套餐', '5', '2021-07-09 11:40:30', '2021-07-09 14:43:45', '1', '1');
INSERT INTO `category` VALUES ('1413384954989060097', '1', '主食', '12', '2021-07-09 14:30:07', '2021-07-09 14:39:19', '1', '1');
INSERT INTO `category` VALUES ('1413386191767674881', '2', '儿童套餐', '6', '2021-07-09 14:35:02', '2021-07-09 14:39:05', '1', '1');

-- ----------------------------
-- Table structure for dish
-- ----------------------------
DROP TABLE IF EXISTS `dish`;
CREATE TABLE `dish` (
  `id` bigint(20) NOT NULL COMMENT '主键',
  `name` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '菜品名称',
  `category_id` bigint(20) NOT NULL COMMENT '菜品分类id',
  `price` decimal(10,2) DEFAULT NULL COMMENT '菜品价格',
  `code` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '商品码',
  `image` varchar(200) COLLATE utf8_bin NOT NULL COMMENT '图片',
  `description` varchar(400) COLLATE utf8_bin DEFAULT NULL COMMENT '描述信息',
  `status` int(11) NOT NULL DEFAULT '1' COMMENT '0 停售 1 起售',
  `sort` int(11) NOT NULL DEFAULT '0' COMMENT '顺序',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `update_time` datetime NOT NULL COMMENT '更新时间',
  `create_user` bigint(20) NOT NULL COMMENT '创建人',
  `update_user` bigint(20) NOT NULL COMMENT '修改人',
  `is_deleted` int(11) NOT NULL DEFAULT '0' COMMENT '是否删除',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `idx_dish_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='菜品管理';

-- ----------------------------
-- Records of dish
-- ----------------------------
INSERT INTO `dish` VALUES ('1397849739276890114', '辣子鸡', '1397844263642378242', '7800.00', '222222222', 'f966a38e-0780-40be-bb52-5699d13cb3d9.jpg', '来自鲜嫩美味的小鸡,值得一尝', '1', '0', '2021-05-27 09:38:43', '2021-05-27 09:38:43', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397850140982161409', '毛氏红烧肉', '1397844263642378242', '6800.00', '123412341234', '0a3b3288-3446-4420-bbff-f263d0c02d8e.jpg', '毛氏红烧肉毛氏红烧肉,确定不来一份?', '1', '0', '2021-05-27 09:40:19', '2021-05-27 09:40:19', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397850392090947585', '组庵鱼翅', '1397844263642378242', '4800.00', '123412341234', '740c79ce-af29-41b8-b78d-5f49c96e38c4.jpg', '组庵鱼翅,看图足以表明好吃程度', '1', '0', '2021-05-27 09:41:19', '2021-05-27 09:41:19', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397850851245600769', '霸王别姬', '1397844263642378242', '12800.00', '123412341234', '057dd338-e487-4bbc-a74c-0384c44a9ca3.jpg', '还有什么比霸王别姬更美味的呢?', '1', '0', '2021-05-27 09:43:08', '2021-05-27 09:43:08', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397851099502260226', '全家福', '1397844263642378242', '11800.00', '23412341234', 'a53a4e6a-3b83-4044-87f9-9d49b30a8fdc.jpg', '别光吃肉啦,来份全家福吧,让你长寿又美味', '1', '0', '2021-05-27 09:44:08', '2021-05-27 09:44:08', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397851370462687234', '邵阳猪血丸子', '1397844263642378242', '13800.00', '1246812345678', '2a50628e-7758-4c51-9fbb-d37c61cdacad.jpg', '看,美味不?来嘛来嘛,这才是最爱吖', '1', '0', '2021-05-27 09:45:12', '2021-05-27 09:45:12', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397851668262465537', '口味蛇', '1397844263642378242', '16800.00', '1234567812345678', '0f4bd884-dc9c-4cf9-b59e-7d5958fec3dd.jpg', '爬行界的扛把子,东兴-口味蛇,让你欲罢不能', '1', '0', '2021-05-27 09:46:23', '2021-05-27 09:46:23', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397852391150759938', '辣子鸡丁', '1397844303408574465', '8800.00', '2346812468', 'ef2b73f2-75d1-4d3a-beea-22da0e1421bd.jpg', '辣子鸡丁,辣子鸡丁,永远的魂', '1', '0', '2021-05-27 09:49:16', '2021-05-27 09:49:16', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397853183287013378', '麻辣兔头', '1397844303408574465', '19800.00', '123456787654321', '2a2e9d66-b41d-4645-87bd-95f2cfeed218.jpg', '麻辣兔头的详细制作,麻辣鲜香,色泽红润,回味悠长', '1', '0', '2021-05-27 09:52:24', '2021-05-27 09:52:24', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397853709101740034', '蒜泥白肉', '1397844303408574465', '9800.00', '1234321234321', 'd2f61d70-ac85-4529-9b74-6d9a2255c6d7.jpg', '多么的有食欲啊', '1', '0', '2021-05-27 09:54:30', '2021-05-27 09:54:30', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397853890262118402', '鱼香肉丝', '1397844303408574465', '3800.00', '1234212321234', '8dcfda14-5712-4d28-82f7-ae905b3c2308.jpg', '鱼香肉丝简直就是我们童年回忆的一道经典菜,上学的时候点个鱼香肉丝盖饭坐在宿舍床上看着肥皂剧,绝了!现在完美复刻一下上学的时候感觉', '1', '0', '2021-05-27 09:55:13', '2021-05-27 09:55:13', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397854652581064706', '麻辣水煮鱼', '1397844303408574465', '14800.00', '2345312·345321', '1fdbfbf3-1d86-4b29-a3fc-46345852f2f8.jpg', '鱼片是买的切好的鱼片,放几个虾,增加味道', '1', '0', '2021-05-27 09:58:15', '2021-05-27 09:58:15', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397854865672679425', '鱼香炒鸡蛋', '1397844303408574465', '2000.00', '23456431·23456', '0f252364-a561-4e8d-8065-9a6797a6b1d3.jpg', '鱼香菜也是川味的特色。里面没有鱼却鱼香味', '1', '0', '2021-05-27 09:59:06', '2021-05-27 09:59:06', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397860242057375745', '脆皮烧鹅', '1397844391040167938', '12800.00', '123456786543213456', 'e476f679-5c15-436b-87fa-8c4e9644bf33.jpeg', '“广东烤鸭美而香,却胜烧鹅说古冈(今新会),燕瘦环肥各佳妙,君休偏重便宜坊”,可见烧鹅与烧鸭在粤菜之中已早负盛名。作为广州最普遍和最受欢迎的烧烤肉食,以它的“色泽金红,皮脆肉嫩,味香可口”的特色,在省城各大街小巷的烧卤店随处可见。', '1', '0', '2021-05-27 10:20:27', '2021-05-27 10:20:27', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397860578738352129', '白切鸡', '1397844391040167938', '6600.00', '12345678654', '9ec6fc2d-50d2-422e-b954-de87dcd04198.jpeg', '白切鸡是一道色香味俱全的特色传统名肴,又叫白斩鸡,是粤菜系鸡肴中的一种,始于清代的民间。白切鸡通常选用细骨农家鸡与沙姜、蒜茸等食材,慢火煮浸白切鸡皮爽肉滑,清淡鲜美。著名的泮溪酒家白切鸡,曾获商业部优质产品金鼎奖。湛江白切鸡更是驰名粤港澳。粤菜厨坛中,鸡的菜式有200余款之多,而最为人常食不厌的正是白切鸡,深受食家青睐。', '1', '0', '2021-05-27 10:21:48', '2021-05-27 10:21:48', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397860792492666881', '烤乳猪', '1397844391040167938', '38800.00', '213456432123456', '2e96a7e3-affb-438e-b7c3-e1430df425c9.jpeg', '广式烧乳猪主料是小乳猪,辅料是蒜,调料是五香粉、芝麻酱、八角粉等,本菜品主要通过将食材放入炭火中烧烤而成。烤乳猪是广州最著名的特色菜,并且是“满汉全席”中的主打菜肴之一。烤乳猪也是许多年来广东人祭祖的祭品之一,是家家都少不了的应节之物,用乳猪祭完先人后,亲戚们再聚餐食用。', '1', '0', '2021-05-27 10:22:39', '2021-05-27 10:22:39', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397860963880316929', '脆皮乳鸽', '1397844391040167938', '10800.00', '1234563212345', '3fabb83a-1c09-4fd9-892b-4ef7457daafa.jpeg', '“脆皮乳鸽”是广东菜中的一道传统名菜,属于粤菜系,具有皮脆肉嫩、色泽红亮、鲜香味美的特点,常吃可使身体强健,清肺顺气。随着菜品制作工艺的不断发展,逐渐形成了熟炸法、生炸法和烤制法三种制作方法。无论那种制作方法,都是在鸽子经过一系列的加工,挂脆皮水后再加工而成,正宗的“脆皮乳鸽皮脆肉嫩、色泽红亮、鲜香味美、香气馥郁。这三种方法的制作过程都不算复杂,但想达到理想的效果并不容易。', '1', '0', '2021-05-27 10:23:19', '2021-05-27 10:23:19', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397861683434139649', '清蒸河鲜海鲜', '1397844391040167938', '38800.00', '1234567876543213456', '1405081e-f545-42e1-86a2-f7559ae2e276.jpeg', '新鲜的海鲜,清蒸是最好的处理方式。鲜,体会为什么叫海鲜。清蒸是广州最经典的烹饪手法,过去岭南地区由于峻山大岭阻隔,交通不便,经济发展起步慢,自家打的鱼放在锅里煮了就吃,没有太多的讲究,但却发现这清淡的煮法能使鱼的鲜甜跃然舌尖。', '1', '0', '2021-05-27 10:26:11', '2021-05-27 10:26:11', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397862198033297410', '老火靓汤', '1397844391040167938', '49800.00', '123456786532455', '583df4b7-a159-4cfc-9543-4f666120b25f.jpeg', '老火靓汤又称广府汤,是广府人传承数千年的食补养生秘方,慢火煲煮的中华老火靓汤,火候足,时间长,既取药补之效,又取入口之甘甜。 广府老火汤种类繁多,可以用各种汤料和烹调方法,烹制出各种不同口味、不同功效的汤来。', '1', '0', '2021-05-27 10:28:14', '2021-05-27 10:28:14', '1', '1', '0');
INSERT INTO `dish` VALUES ('1397862477831122945', '上汤焗龙虾', '1397844391040167938', '108800.00', '1234567865432', '5b8d2da3-3744-4bb3-acdc-329056b8259d.jpeg', '上汤焗龙虾是一道色香味俱全的传统名菜,属于粤菜系。此菜以龙虾为主料,配以高汤制成的一道海鲜美食。本品肉质洁白细嫩,味道鲜美,蛋白质含量高,脂肪含量低,营养丰富。是色香味俱全的传统名菜。', '1', '0', '2021-05-27 10:29:20', '2021-05-27 10:29:20', '1', '1', '0');
INSERT INTO `dish` VALUES ('1413342036832100354', '北冰洋', '1413341197421846529', '500.00', '', 'c99e0aab-3cb7-4eaa-80fd-f47d4ffea694.png', '', '1', '0', '2021-07-09 11:39:35', '2021-07-09 15:12:18', '1', '1', '0');
INSERT INTO `dish` VALUES ('1413384757047271425', '王老吉', '1413341197421846529', '500.00', '', '00874a5e-0df2-446b-8f69-a30eb7d88ee8.png', '', '1', '0', '2021-07-09 14:29:20', '2021-07-12 09:09:16', '1', '1', '0');
INSERT INTO `dish` VALUES ('1413385247889891330', '米饭', '1413384954989060097', '200.00', '', 'ee04a05a-1230-46b6-8ad5-1a95b140fff3.png', '', '1', '0', '2021-07-09 14:31:17', '2021-07-11 16:35:26', '1', '1', '0');

-- ----------------------------
-- Table structure for dish_flavor
-- ----------------------------
DROP TABLE IF EXISTS `dish_flavor`;
CREATE TABLE `dish_flavor` (
  `id` bigint(20) NOT NULL COMMENT '主键',
  `dish_id` bigint(20) NOT NULL COMMENT '菜品',
  `name` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '口味名称',
  `value` varchar(500) COLLATE utf8_bin DEFAULT NULL COMMENT '口味数据list',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `update_time` datetime NOT NULL COMMENT '更新时间',
  `create_user` bigint(20) NOT NULL COMMENT '创建人',
  `update_user` bigint(20) NOT NULL COMMENT '修改人',
  `is_deleted` int(11) NOT NULL DEFAULT '0' COMMENT '是否删除',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='菜品口味关系表';

-- ----------------------------
-- Records of dish_flavor
-- ----------------------------
INSERT INTO `dish_flavor` VALUES ('1397849417888346113', '1397849417854791681', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 09:37:27', '2021-05-27 09:37:27', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397849739297861633', '1397849739276890114', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-27 09:38:43', '2021-05-27 09:38:43', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397849739323027458', '1397849739276890114', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 09:38:43', '2021-05-27 09:38:43', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397849936421761025', '1397849936404983809', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-27 09:39:30', '2021-05-27 09:39:30', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397849936438538241', '1397849936404983809', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 09:39:30', '2021-05-27 09:39:30', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397850141015715841', '1397850140982161409', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-27 09:40:19', '2021-05-27 09:40:19', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397850141040881665', '1397850140982161409', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 09:40:19', '2021-05-27 09:40:19', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397850392120307713', '1397850392090947585', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 09:41:19', '2021-05-27 09:41:19', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397850392137084929', '1397850392090947585', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 09:41:19', '2021-05-27 09:41:19', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397850630734262274', '1397850630700707841', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-27 09:42:16', '2021-05-27 09:42:16', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397850630755233794', '1397850630700707841', '辣度', '[\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 09:42:16', '2021-05-27 09:42:16', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397850851274960898', '1397850851245600769', '忌口', '[\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-27 09:43:08', '2021-05-27 09:43:08', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397850851283349505', '1397850851245600769', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 09:43:08', '2021-05-27 09:43:08', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397851099523231745', '1397851099502260226', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-27 09:44:08', '2021-05-27 09:44:08', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397851099527426050', '1397851099502260226', '辣度', '[\"不辣\",\"微辣\",\"中辣\"]', '2021-05-27 09:44:08', '2021-05-27 09:44:08', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397851370483658754', '1397851370462687234', '温度', '[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]', '2021-05-27 09:45:12', '2021-05-27 09:45:12', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397851370483658755', '1397851370462687234', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-27 09:45:12', '2021-05-27 09:45:12', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397851370483658756', '1397851370462687234', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 09:45:12', '2021-05-27 09:45:12', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397851668283437058', '1397851668262465537', '温度', '[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]', '2021-05-27 09:46:23', '2021-05-27 09:46:23', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397852391180120065', '1397852391150759938', '忌口', '[\"不要葱\",\"不要香菜\",\"不要辣\"]', '2021-05-27 09:49:16', '2021-05-27 09:49:16', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397852391196897281', '1397852391150759938', '辣度', '[\"不辣\",\"微辣\",\"重辣\"]', '2021-05-27 09:49:16', '2021-05-27 09:49:16', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397853183307984898', '1397853183287013378', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 09:52:24', '2021-05-27 09:52:24', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397853423486414850', '1397853423461249026', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 09:53:22', '2021-05-27 09:53:22', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397853709126905857', '1397853709101740034', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-27 09:54:30', '2021-05-27 09:54:30', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397853890283089922', '1397853890262118402', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 09:55:13', '2021-05-27 09:55:13', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397854133632413697', '1397854133603053569', '温度', '[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]', '2021-05-27 09:56:11', '2021-05-27 09:56:11', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397854652623007745', '1397854652581064706', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-27 09:58:15', '2021-05-27 09:58:15', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397854652635590658', '1397854652581064706', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 09:58:15', '2021-05-27 09:58:15', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397854865735593986', '1397854865672679425', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 09:59:06', '2021-05-27 09:59:06', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397855742303186946', '1397855742273826817', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 10:02:35', '2021-05-27 10:02:35', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397855906497605633', '1397855906468245506', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-27 10:03:14', '2021-05-27 10:03:14', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397856190573621250', '1397856190540066818', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 10:04:21', '2021-05-27 10:04:21', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397859056709316609', '1397859056684150785', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 10:15:45', '2021-05-27 10:15:45', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397859277837217794', '1397859277812051969', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 10:16:37', '2021-05-27 10:16:37', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397859487502086146', '1397859487476920321', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 10:17:27', '2021-05-27 10:17:27', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397859757061615618', '1397859757036449794', '甜味', '[\"无糖\",\"少糖\",\"半躺\",\"多糖\",\"全糖\"]', '2021-05-27 10:18:32', '2021-05-27 10:18:32', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397860242086735874', '1397860242057375745', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 10:20:27', '2021-05-27 10:20:27', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397860963918065665', '1397860963880316929', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 10:23:19', '2021-05-27 10:23:19', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397861135754506242', '1397861135733534722', '甜味', '[\"无糖\",\"少糖\",\"半躺\",\"多糖\",\"全糖\"]', '2021-05-27 10:24:00', '2021-05-27 10:24:00', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397861370035744769', '1397861370010578945', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-27 10:24:56', '2021-05-27 10:24:56', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397861683459305474', '1397861683434139649', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-27 10:26:11', '2021-05-27 10:26:11', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397861898467717121', '1397861898438356993', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-27 10:27:02', '2021-05-27 10:27:02', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397862198054268929', '1397862198033297410', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-27 10:28:14', '2021-05-27 10:28:14', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1397862477835317250', '1397862477831122945', '辣度', '[\"不辣\",\"微辣\",\"中辣\"]', '2021-05-27 10:29:20', '2021-05-27 10:29:20', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398089545865015297', '1398089545676271617', '温度', '[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]', '2021-05-28 01:31:38', '2021-05-28 01:31:38', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398089782323097601', '1398089782285348866', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-28 01:32:34', '2021-05-28 01:32:34', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398090003262255106', '1398090003228700673', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-28 01:33:27', '2021-05-28 01:33:27', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398090264554811394', '1398090264517062657', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-28 01:34:29', '2021-05-28 01:34:29', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398090455399837698', '1398090455324340225', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-28 01:35:14', '2021-05-28 01:35:14', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398090685449023490', '1398090685419663362', '温度', '[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]', '2021-05-28 01:36:09', '2021-05-28 01:36:09', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398090825358422017', '1398090825329061889', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-28 01:36:43', '2021-05-28 01:36:43', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398091007051476993', '1398091007017922561', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-28 01:37:26', '2021-05-28 01:37:26', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398091296164851713', '1398091296131297281', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-28 01:38:35', '2021-05-28 01:38:35', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398091546531246081', '1398091546480914433', '忌口', '[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]', '2021-05-28 01:39:35', '2021-05-28 01:39:35', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398091729809747969', '1398091729788776450', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-28 01:40:18', '2021-05-28 01:40:18', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398091889499484161', '1398091889449152513', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-28 01:40:56', '2021-05-28 01:40:56', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398092095179763713', '1398092095142014978', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-28 01:41:45', '2021-05-28 01:41:45', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398092283877306370', '1398092283847946241', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-28 01:42:30', '2021-05-28 01:42:30', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398094018939236354', '1398094018893099009', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-28 01:49:24', '2021-05-28 01:49:24', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1398094391494094850', '1398094391456346113', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-05-28 01:50:53', '2021-05-28 01:50:53', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1399574026165727233', '1399305325713600514', '辣度', '[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]', '2021-06-01 03:50:25', '2021-06-01 03:50:25', '1399309715396669441', '1399309715396669441', '0');
INSERT INTO `dish_flavor` VALUES ('1413389540592263169', '1413384757047271425', '温度', '[\"常温\",\"冷藏\"]', '2021-07-12 09:09:16', '2021-07-12 09:09:16', '1', '1', '0');
INSERT INTO `dish_flavor` VALUES ('1413389684020682754', '1413342036832100354', '温度', '[\"常温\",\"冷藏\"]', '2021-07-09 15:12:18', '2021-07-09 15:12:18', '1', '1', '0');

-- ----------------------------
-- Table structure for employee
-- ----------------------------
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
  `id` bigint(20) NOT NULL COMMENT '主键',
  `name` varchar(32) COLLATE utf8_bin NOT NULL COMMENT '姓名',
  `username` varchar(32) COLLATE utf8_bin NOT NULL COMMENT '用户名',
  `password` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '密码',
  `phone` varchar(11) COLLATE utf8_bin NOT NULL COMMENT '手机号',
  `sex` varchar(2) COLLATE utf8_bin NOT NULL COMMENT '性别',
  `id_number` varchar(18) COLLATE utf8_bin NOT NULL COMMENT '身份证号',
  `status` int(11) NOT NULL DEFAULT '1' COMMENT '状态 0:禁用,1:正常',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `update_time` datetime NOT NULL COMMENT '更新时间',
  `create_user` bigint(20) NOT NULL COMMENT '创建人',
  `update_user` bigint(20) NOT NULL COMMENT '修改人',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='员工信息';

-- ----------------------------
-- Records of employee
-- ----------------------------
INSERT INTO `employee` VALUES ('1', '管理员', 'admin', 'e10adc3949ba59abbe56e057f20f883e', '13812312312', '1', '110101199001010047', '1', '2021-05-06 17:20:07', '2021-05-10 02:24:09', '1', '1');

-- ----------------------------
-- Table structure for orders
-- ----------------------------
DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
  `id` bigint(20) NOT NULL COMMENT '主键',
  `number` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '订单号',
  `status` int(11) NOT NULL DEFAULT '1' COMMENT '订单状态 1待付款,2待派送,3已派送,4已完成,5已取消',
  `user_id` bigint(20) NOT NULL COMMENT '下单用户',
  `address_book_id` bigint(20) NOT NULL COMMENT '地址id',
  `order_time` datetime NOT NULL COMMENT '下单时间',
  `checkout_time` datetime NOT NULL COMMENT '结账时间',
  `pay_method` int(11) NOT NULL DEFAULT '1' COMMENT '支付方式 1微信,2支付宝',
  `amount` decimal(10,2) NOT NULL COMMENT '实收金额',
  `remark` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '备注',
  `phone` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  `address` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  `user_name` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  `consignee` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='订单表';

-- ----------------------------
-- Records of orders
-- ----------------------------

-- ----------------------------
-- Table structure for order_detail
-- ----------------------------
DROP TABLE IF EXISTS `order_detail`;
CREATE TABLE `order_detail` (
  `id` bigint(20) NOT NULL COMMENT '主键',
  `name` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '名字',
  `image` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '图片',
  `order_id` bigint(20) NOT NULL COMMENT '订单id',
  `dish_id` bigint(20) DEFAULT NULL COMMENT '菜品id',
  `setmeal_id` bigint(20) DEFAULT NULL COMMENT '套餐id',
  `dish_flavor` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '口味',
  `number` int(11) NOT NULL DEFAULT '1' COMMENT '数量',
  `amount` decimal(10,2) NOT NULL COMMENT '金额',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='订单明细表';

-- ----------------------------
-- Records of order_detail
-- ----------------------------

-- ----------------------------
-- Table structure for setmeal
-- ----------------------------
DROP TABLE IF EXISTS `setmeal`;
CREATE TABLE `setmeal` (
  `id` bigint(20) NOT NULL COMMENT '主键',
  `category_id` bigint(20) NOT NULL COMMENT '菜品分类id',
  `name` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '套餐名称',
  `price` decimal(10,2) NOT NULL COMMENT '套餐价格',
  `status` int(11) DEFAULT NULL COMMENT '状态 0:停用 1:启用',
  `code` varchar(32) COLLATE utf8_bin DEFAULT NULL COMMENT '编码',
  `description` varchar(512) COLLATE utf8_bin DEFAULT NULL COMMENT '描述信息',
  `image` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '图片',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `update_time` datetime NOT NULL COMMENT '更新时间',
  `create_user` bigint(20) NOT NULL COMMENT '创建人',
  `update_user` bigint(20) NOT NULL COMMENT '修改人',
  `is_deleted` int(11) NOT NULL DEFAULT '0' COMMENT '是否删除',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `idx_setmeal_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='套餐';

-- ----------------------------
-- Records of setmeal
-- ----------------------------
INSERT INTO `setmeal` VALUES ('1415580119015145474', '1413386191767674881', '儿童套餐A计划', '4000.00', '1', '', '', '61d20592-b37f-4d72-a864-07ad5bb8f3bb.jpg', '2021-07-15 15:52:55', '2021-07-15 15:52:55', '1415576781934608386', '1415576781934608386', '0');

-- ----------------------------
-- Table structure for setmeal_dish
-- ----------------------------
DROP TABLE IF EXISTS `setmeal_dish`;
CREATE TABLE `setmeal_dish` (
  `id` bigint(20) NOT NULL COMMENT '主键',
  `setmeal_id` varchar(32) COLLATE utf8_bin NOT NULL COMMENT '套餐id ',
  `dish_id` varchar(32) COLLATE utf8_bin NOT NULL COMMENT '菜品id',
  `name` varchar(32) COLLATE utf8_bin DEFAULT NULL COMMENT '菜品名称 (冗余字段)',
  `price` decimal(10,2) DEFAULT NULL COMMENT '菜品原价(冗余字段)',
  `copies` int(11) NOT NULL COMMENT '份数',
  `sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `update_time` datetime NOT NULL COMMENT '更新时间',
  `create_user` bigint(20) NOT NULL COMMENT '创建人',
  `update_user` bigint(20) NOT NULL COMMENT '修改人',
  `is_deleted` int(11) NOT NULL DEFAULT '0' COMMENT '是否删除',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='套餐菜品关系';

-- ----------------------------
-- Records of setmeal_dish
-- ----------------------------
INSERT INTO `setmeal_dish` VALUES ('1415580119052894209', '1415580119015145474', '1397862198033297410', '老火靓汤', '49800.00', '1', '0', '2021-07-15 15:52:55', '2021-07-15 15:52:55', '1415576781934608386', '1415576781934608386', '0');
INSERT INTO `setmeal_dish` VALUES ('1415580119061282817', '1415580119015145474', '1413342036832100354', '北冰洋', '500.00', '1', '0', '2021-07-15 15:52:55', '2021-07-15 15:52:55', '1415576781934608386', '1415576781934608386', '0');
INSERT INTO `setmeal_dish` VALUES ('1415580119069671426', '1415580119015145474', '1413385247889891330', '米饭', '200.00', '1', '0', '2021-07-15 15:52:55', '2021-07-15 15:52:55', '1415576781934608386', '1415576781934608386', '0');

-- ----------------------------
-- Table structure for shopping_cart
-- ----------------------------
DROP TABLE IF EXISTS `shopping_cart`;
CREATE TABLE `shopping_cart` (
  `id` bigint(20) NOT NULL COMMENT '主键',
  `name` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '名称',
  `image` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '图片',
  `user_id` bigint(20) NOT NULL COMMENT '主键',
  `dish_id` bigint(20) DEFAULT NULL COMMENT '菜品id',
  `setmeal_id` bigint(20) DEFAULT NULL COMMENT '套餐id',
  `dish_flavor` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '口味',
  `number` int(11) 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=utf8 COLLATE=utf8_bin COMMENT='购物车';

-- ----------------------------
-- Records of shopping_cart
-- ----------------------------

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL COMMENT '主键',
  `name` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '姓名',
  `phone` varchar(100) COLLATE utf8_bin NOT NULL COMMENT '手机号',
  `sex` varchar(2) COLLATE utf8_bin DEFAULT NULL COMMENT '性别',
  `id_number` varchar(18) COLLATE utf8_bin DEFAULT NULL COMMENT '身份证号',
  `avatar` varchar(500) COLLATE utf8_bin DEFAULT NULL COMMENT '头像',
  `status` int(11) DEFAULT '0' COMMENT '状态 0:禁用,1:正常',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='用户信息';

依赖建立和版本控制

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.1</version>
</parent>
    <groupId>com.heyu</groupId>
    <artifactId>reggie_take_out</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>15</maven.compiler.source>
        <maven.compiler.target>15</maven.compiler.target>
        <mybatis-plus.version>3.5.2</mybatis-plus.version>
        <fastjson.version>2.0.6</fastjson.version>
        <commons-lang.version>2.6</commons-lang.version>
        <durid.version>1.2.11</durid.version>
        <maven-plugin.version>2.7.1</maven-plugin.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>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>${mybatis-plus.version}</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>${fastjson.version}</version>
    </dependency>
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>${commons-lang.version}</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>${durid.version}</version>
    </dependency>

</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>${maven-plugin.version}</version>
        </plugin>
    </plugins>
</build>
</project>

配置文件

建立普通环境和开发环境,默认激活Dev 环境

spring:
  profiles:
    active: dev

Application-dev.yml

server:
  port: 8080
spring:
  application:
    name: reggie_take_out
  datasource:
    druid:
      username: root
      password: root1234
      url: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
    type: com.alibaba.druid.pool.DruidDataSource
mybatis-plus:
  configuration:
    #在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
    map-underscore-to-camel-case: true
    #把 SQL 的查询的过程输出到控制台
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      id-type: assign_id

主启动类

@Slf4j
@SpringBootApplication
public class ReggieApplication {
    public static void main(String[] args) {
        SpringApplication.run(ReggieApplication.class,args);
        log.info("项目启动成功.....");
    }
}

配置静态资源映射

package com.heyu.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;
@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry){
        log.info("开始静态资源映射");
        registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
        registry.addResourceHandler("front/**").addResourceLocations("classpath:/front/");
    }
}

后台登录功能开发

需求分析

前端 URL 发送的请求—>接收到 Controller—>Service—>Mapper—>DataBase

导入返回结果类 R

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

entity.Employee

@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;

}

Mapper.EmployeeMapper

@Mapper
public interface EmployeeMapper extends BaseMapper<Employee> {
}

Service.EmployeeService

public interface EmployeeService extends IService<Employee> {
}

Service.EmployeeServiceImpl

@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper,Employee> implements EmployeeService {

}

业务逻辑

1.将页面提交的密码 password 进行 md5 加密处理
2.根据页面提交的用户名 username 查询数据库
3.如果没有查询到就返回---登录失败
4.密码比对,如果不一致,返回---登录失败
5.查看员工状态,如果为已禁用状态,则返回---员工已禁用
6.登录成功,将员工 ID 存入 session 并返回---登录成功

Controller.EmployeeController

@RestController
@Slf4j
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    @PostMapping("/login") //使用restful风格开发
    public R<Employee> login(HttpServletRequest request, @RequestBody Employee employee){//接收前端的json数据,这个json数据是在请求体中的
        //这里为什么还有接收一个request对象的数据?
        //登陆成功后,我们需要从请求中获取员工的id,并且把这个id存到session中,这样我们想要获取登陆对象的时候就可以随时获取

        //1、将页面提交的密码password进行md5加密处理
        String password = employee.getPassword();//从前端用户登录拿到的用户密码
        password = DigestUtils.md5DigestAsHex(password.getBytes());//对用户密码进行加密

        //2、根据页面提交的用户名username查询数据库
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Employee::getUsername,employee.getUsername());
        //在设计数据库的时候我们对username使用了唯一索引,所以这里可以使用getOne方法
        Employee emp = employeeService.getOne(queryWrapper);//这里的切入Wrapper是什么?

        //3、如果没有查询到则返回登录失败结果
        if (emp == null ){
            return R.error("用户不存在");
        }

        //4、密码比对,如果不一致则返回登录失败结果
        if (!emp.getPassword().equals(password)){
            //emp.getPassword()用户存在后从数据库查询到的密码(加密状态的)  password是前端用户自己输入的密码(已经加密处理)
            return R.error("密码不正确");
        }

        //5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果
        if (emp.getStatus() == 0){
            return R.error("账号已禁用");
        }

        //6、登录成功,将员工id存入Session并返回登录成功结果
        request.getSession().setAttribute("employee",emp.getId());
        //把从数据库中查询到的用户返回出去
        return R.success(emp);
    }
}

Day02

问题

登录报错 406

Debug 错误内容

JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@73b865ee] will not be managed by Spring
==>  Preparing: SELECT id,username,name,password,phone,sex,id_number,status,create_time,update_time,create_user,update_user FROM employee WHERE (username = ?)
==> Parameters: admin(String)
<==    Columns: id, username, name, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user
<==        Row: 1, admin, 管理员, e10adc3949ba59abbe56e057f20f883e, 13812312312, 1, 110101199001010047, 1, 2021-05-06 17:20:07, 2021-05-10 02:24:09, 1, 1
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6e4dbf4a]
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@6c6f3c95] will not be managed by Spring
==>  Preparing: SELECT id,username,name,password,phone,sex,id_number,status,create_time,update_time,create_user,update_user FROM employee WHERE (username = ?)
==> Parameters: admin(String)
<==    Columns: id, username, name, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user
<==        Row: 1, admin, 管理员, e10adc3949ba59abbe56e057f20f883e, 13812312312, 1, 110101199001010047, 1, 2021-05-06 17:20:07, 2021-05-10 02:24:09, 1, 1
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3d6369a1]

第一次解决:406 异常—>500 异常

解决方法:

@RequestMapping(value="/employee",produces = "application/json")

猜测:客户端无法解析服务端返回的内容,客户端希望返回的数据格式是 JSON 格式,但我们实际返回的是 text/html格式,所以使用@Requestmapping注解的 produces 属性,设置返回数据的类型以及编码形式

可以有如下写法:

@RequestMapping(value="/xxx",produces = {"application/json;charset=UTF-8"})@RequestMapping(value="/xxx",produces = {"application/xml;charset=UTF-8"})

问题解决:重新创建项目,问题原因是依赖版本不匹配,更换依赖后解决

404 路径错误,500 代码功能错误

后台退出功能开发

需求分析

员工登录成功后,页面跳转到后台系统首页面(backend/index.html),此时会显示当前登录用户的姓名

如果员工需要退出系统,直接点击右侧的退出按钮就可以退出系统,退出系统后页面应跳转回登录页面

代码开发功能流程

1.用户点击页面--退出 logout,发送请求,请求地址为/employee/logout,请求方式为 POST
2.任务内容:
(1)清理 session 中的 ID
(2)返回结果
    @PostMapping(value = "/logout")
    public R<String> logout(HttpServletRequest request){
        request.removeAttribute("employee");
        return R.success("退出成功");
    }

完善登录功能

问题分析

前面完成的后台系统的员工登录功能开发,但是还存在问题:用户如果不登录而是知己访问系统首页面,照样可以正常访问,这种设计显然不合理,我们希望设计:只有登录成功才能访问到系统中的页面,如果没有登录则跳转到登录页面

采用过滤器或者拦截器来实现,在过滤器或者拦截器中判断用户是否已经完成登录,如果没有登录则跳转到登录页面

实现步骤:

1.创建自定义过滤器 LoginCheckFilter
2.在启动类上加入注解@ServletComponentScan
3.完善过滤器的处理逻辑
@Slf4j
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        log.info("拦截到的请求:{}",request.getRequestURI());
        filterChain.doFilter(request,response);
    }

同时需要在启动类添加注解@ServletComponentScan

URI&&URL

URI:统一资源标识符

用来标识Web 上可访问的任意类型的资源(HTML,视频,音频,程序等)

URI 由三部分组成:

  1. 访问资源的命名机制:比如 com(公司)、gov(政府)、edu(教育组织)
  2. 存放资源的主机名(计算机的 IP 号)
  3. 标识资源自身的路径

URL:统一资源定位符

理解为 Internet 资源的地址,用来定义引用地址的字符串,用于定位一个资源的位置以及它所使用的协议

URL 由七部分组成:

  1. 所使用的协议(HTTP,FTP)
  2. 服务器的位置(IP)
  3. 服务器端口号(0~65535)
  4. 资源所在的路径(path)
  5. 参数(访问该资源时,携带的参数信息)
  6. 片段(发给 HTTP 服务器的数据)
  7. 登录信息(authority)

URI 是 URL 的父类,URL 是 URI 的子集

过滤器的处理逻辑

1.获取本次请求的 URI
2.判断本次请求是否需要处理
3.如果不需要处理,则直接放行
4.判断登录状态,如果已登录,则直接放行
5.如果未登录则返回未登录结果

过滤器代码实现

package com.heyu.reggie.filter;

import com.alibaba.fastjson.JSON;
import com.heyu.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;
@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 requestURI = request.getRequestURI();
        //定义不需要处理的请求路径
        String[] urls = new String[]{
          "/employee/login","/employee/logout",
          "/backend/**","/front/**"
        };
        log.info("拦截到请求:{}",requestURI);
        //        2.判断本次请求是否需要处理
        boolean check = check(urls,requestURI);
        //        3.如果不需要处理,则直接放行
        if(check){
            log.info("本次请求{}不需要处理",requestURI);
            filterChain.doFilter(request,response);
            return;
        }
        //        4.判断登录状态,如果已登录,则直接放行
        if(request.getSession().getAttribute("employee")!=null){
            log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("employee"));
            filterChain.doFilter(request,response);
            return;
        }
        //        5.如果未登录则返回未登录结果
        //      通过输出流的方式向客户端页面响应数据,具体响应什么数据,要看前端的需求,然后前段会根据登录状态做页面跳转
        log.info("用户未登录");
        response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
    }


    /*
    * @Auther: heyu
    * @Description:路径匹配,检查本次请求是否能否方形
    * @DateTime:
    * @Params: url
    */
    public boolean check(String[] urls, String requestURI){
        for(String url: urls){
            //将浏览器发过来的请求和定义的不拦截的 URL 进行比较,匹配就放行
            boolean match = PATH_MATCHER.match(url,requestURI);
            if (match){
                return true;
            }
        }
        return false;

    }

}

员工管理模块

需求分析

  1. 前端页面发送 Ajax 请求,将新增员工页面中输入的数据以 JSON 的形式提交到服务端
  2. 服务端 Controller 接收页面提交的数据并调用 Service 将数据保存
  3. Service 调用 Mapper 操作数据库,保存数据

新增员工代码

  /**
     * 新增员工
     * @param employee
     * @return
     */
    @PostMapping()//因为请求就是 /employee 在类上已经写了,所以咱俩不用再写了
    public R<String> save(HttpServletRequest request,@RequestBody Employee employee){

        //对新增的员工设置初始化密码123456,需要进行md5加密处理,后续员工可以直接修改密码
        employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));

        employee.setCreateTime(LocalDateTime.now());
        employee.setUpdateTime(LocalDateTime.now());

        //获得当前登录用户的id
        Long empId = (Long) request.getSession().getAttribute("employee");

        employee.setCreateUser(empId); //创建人的id,就是当前用户的id(在进行添加操作的id)
        employee.setUpdateUser(empId);//最后的更新人是谁
        //mybatis提供的新增方法
        employeeService.save(employee);

        return R.success("新增员工成功");
    }

功能测试:登陆之后,点击添加,然后确认,然后去数据库看一下新增数据成功没,新增成功,那就表示代码可以执行; 注意:但是因为我们把username设置为唯一索引,所以下次再新增用户的时候,就会出现异常,这个异常是MySQL数据库抛出来的;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XEabtJIY-1657719042133)(单体项目-瑞吉外卖.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pyq5p2l5b6I6ZW_77yM5Yir5Y-q55yL55y85YmN,size_20,color_FFFFFF,t_70,g_se,x_16.png)]

全局异常处理

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /*
     * @description:处理
     * @author: heyu 
     * @date: 2022-7-10 
     * @param:
     * @return: 
     **/
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public R<String> exceptionHandler(SQLIntegrityConstraintViolationException e){
        log.error(e.getMessage());
        if (e.getMessage().contains("Duplicate entry")){
          //获取已经存在的用户名,这里是从报错的异常信息中获取的
            String[] split = e.getMessage().split(" ");
            String msg = split[2]+"用户名已存在";
            return R.error(msg);
        }
        return R.error("未知错误");
    }
}

使用@ExceptionHandler(),括号内表示本方法所捕捉的异常类型

总结

  1. 根据产品原型明确业务需求
  2. 重点分析数据的流转过程和数据格式
  3. 通过 debug 断点调试跟踪程序执行过程

Day03

员工信息分页查询

代码开发

程序执行过程:

1. 页面发送 Ajax 请求,将分页查询参数(page,PageSize,name)提交到服务端
2. 服务端 Controller 接收页面提交的数据并调用 Service 查询数据
3. Service 调用 Mapper 操作数据库,查询分页数据
4. Controller 将查询到的分页数据,转为 JSON,响应给页面
5. 页面接收到分页数据并通过 ElementUI 的 Table 组件展示到页面上

配置 mybaits-plus 分页插件拦截器

/*
 * @description:配置 mybatis-plus 提供的分页插件拦截器
 * @author: heyu
 * @date: 2022.7.10
 * @param:
 * @return: mybatisPlusInterceptor
 **/
@Configuration
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;

    }

}

controller-分页控制

 /*
     * @description:分页控制输出和查询
     * @author: heyu 
     * @date: 2022.7.10
     * @param: int page, int pageSize,String name
     * @return: R.success(pageInfo)
     **/
    @GetMapping("/page")
    public R<Page> page(int page,int pageSize,String name){
        //此处之所以是返回 page 对象(mybatis-plus 的 page 对象),是因为前端需要这些分页数据(比如当前页,总页数)
        //使用日志输出,判断一下前端传回来的分页数据有没有被我们接收到
        log.info("page={},pageSize={},name={}",page,pageSize,name);
        //构造分页器,即 page 对象
        Page pageInfo = new Page(page,pageSize);

        //构造条件构造器,即动态的封装前端传过来的过滤条件,加泛型
        LambdaQueryWrapper<Employee> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //根据条件查询,如果搜索框不为空,我们就同样执行搜索框中的限定条件
        lambdaQueryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name);
        //添加一个排序条件
        lambdaQueryWrapper.orderByDesc(Employee::getUpdateTime);
        //执行查询,mp已经封装好了
        employeeService.page(pageInfo,lambdaQueryWrapper);

        return R.success(pageInfo);
    }
}

Day04

启用/禁用员工账号

需求分析

在员工管理列表界面,可以对某个员工账号进行启用或者禁用操作。账号禁用的员工不能登陆系统,启用的用户才能登录

需要注意的是:只有管理员(admin用户)才可以对其他普通用户进行启用操作,禁用操作,所以普通用户登录系统后启用,禁用按钮不显示;

并且如果某个员工账号的状态为正常,则按钮显示为’‘禁用’,如果员工账号状态为已禁用,则按钮显示为“启用”。

普通员工登录系统后,启用,禁用按钮不显示;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v7hGktZx-1657719042134)(单体项目-瑞吉外卖.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pyq5p2l5b6I6ZW_77yM5Yir5Y-q55yL55y85YmN,size_18,color_FFFFFF,t_70,g_se,x_16.png)]

注意:这里修改状态码要反着来,因为正常的用户你只能把它设置为禁用;已经禁用的账号你只能把它设置为正常

根据 id 修改员工信息

  /**
     * 根据id修改员工信息
     * @param employee
     * @return
     */
    @PutMapping
    public R<String> update(HttpServletRequest request,@RequestBody Employee employee){
        log.info(employee.toString());

        Long empId = (Long)request.getSession().getAttribute("employee");
        employee.setUpdateTime(LocalDateTime.now());
        employee.setUpdateUser(empId);
        employeeService.updateById(employee);

        return R.success("员工信息修改成功");
    }

丢失问题

修改员工状态,前端显示修改成功,数据库字段却并没有发生变化,原因是因为后台的 SQL 语句使用的 id 和数据库字段的 ID 不同

原因是:mybatis-plus对id使用了雪花算法,所以存入数据库中的id是19为长度,但是前端的js只能保证数据的前16位的数据的精度,对我们id后面三位数据进行了四舍五入,所以就出现了精度丢失;就会出现前度传过来的id和数据里面的id不匹配,就没办法正确的修改到我们想要的数据;

问题解决

自定义消息转换器

既然js对long型的数据会进行精度丢失,那么我们就对数据进行转型,我们可以在服务端(Java端)给页面响应json格式的数据时进行处理,将long型的数据统一转换为string字符串;

代码实现步骤

  1. 提供对象转换器 JacksonObjectMapper,基于 Jackson 进行 Java 对象到 JSON 数据的转换
  1. 在配置类的 WebMvcConfig 中扩展 SpringMVC 的消息转换器,在此消息转换器中使用提供的对象转换器进行 Java 对象到 json数据的转换

自定义消息转换器

/*
* 对象映射器:基于 Jackson 将 Java 对象转为 JSON,或者将 JSON 转为 JSON 对象
* 将 JSON 解析为 Java 对象的过程成为----从 JSON 反序列化 Java 对象
* 从 Java 对象生成 JSON 的过程称为----序列化 Java 对象到 JSON
 */

public class JasksonObjectMapper extends ObjectMapper {
    //将日期的格式从数组的形式转化为易读的 String 类型
    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    public JasksonObjectMapper(){
        super();
        //接收到位置属性时不报异常
        this.configure(FAIL_ON_UNKNOWN_PROPERTIES,false);
        //反序列化时,属性不存在的兼容处理
        this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        SimpleModule simpleModule = new SimpleModule()
                .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))

                .addSerializer(BigInteger.class, ToStringSerializer.instance)
                .addSerializer(Long.class, ToStringSerializer.instance)
                .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));

        //注册功能模块 例如,可以添加自定义序列化器和反序列化器
        this.registerModule(simpleModule);
    }

}

在前面的webMvcConfig 配置类中扩展spring mvc 的消息转换器,在此消息转换器中使用spring提供的对象转换器进行Java对象到json数据的转换

 /*
      * @description:将自定义消息转换器配置到 MVC 框架中
      * @author: heyu 
      * @date: 2022/7/11 15:05
      * @Param: null
      * @return: 
     **/
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>>converters){
        log.info("扩展消息转换器...");
        //创建消息转换器对象
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        //设置消息转换器,底层使用 Jackson 将 Java 对象转为 JSON
        //下面这行代码将我们在 common 包中自己设置的消息转换器加入到 MNC 框架的转换器集合中
        messageConverter.setObjectMapper(new JasksonObjectMapper());
        //转换器有先后顺序,我们将自己配置的转换器设置为第一优先级
        converters.add(0,messageConverter);
    }

编辑员工信息

在员工管理列表页面中点击编辑按钮,跳转到编辑页面,在编辑页面回显员工信息并进行修改,最后点击保存按钮完成编辑操作

代码开发

  1. 点击编辑按钮,页面跳转到 add.html,并在 URL 中携带员工 ID
  2. 在 add.html页面获取 URL 中的参数「员工 ID」
  3. 发送 Ajax 请求,请求服务端,同时提交员工 ID
  4. 服务端接受请求,根据员工 ID 查询员工信息,将员工信息以 JSON 形式响应给页面
  5. 页面接受服务端响应的 JSON 数据,通过vue 的数据绑定进行员工信息回显
  6. 点击保存按钮,发送 Ajax 请求,将页面中的员工信息以 JSON 方式提交给服务端
  7. 服务端接受员工信息,并进行处理,完成后交给页面响应
  8. 页面接受到服务端响应信息后进行相应处理

菜品分类管理

Day04

公共字段自动填充

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tn0O2UOS-1657719042134)(单体项目-瑞吉外卖.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pyq5p2l5b6I6ZW_77yM5Yir5Y-q55yL55y85YmN,size_20,color_FFFFFF,t_70,g_se,x_16-7524746.png)]

代码实现

  1. 在实体类的属性上加入@TableField注解,指定自动填充的策略
  2. 按照框架要求编写元数据对象处理器,在此类中统一为公共字段赋值,此类需要实现 MetaObjecthandler接口

在实体类中添加@TableField注解

    @TableField(fill = FieldFill.INSERT)//插入时填充字段
    private LocalDateTime createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)//插入和更新时填充字段
    private LocalDateTime updateTime;

    @TableField(fill = FieldFill.INSERT)//插入时填充字段
    private Long createUser;

    @TableField(fill = FieldFill.INSERT_UPDATE)//插入和更新时填充字段
    private Long updateUser;

编写 MetaObjectHandler类,实现 MetaObjectHandler 接口,从而接手这些公共字段

/*
 *@description:自定义元数据对象处理器
 *@createTime:2022/7/11 15:44
 *@author:heyu
*/

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject){
        metaObject.setValue("createTime", LocalDateTime.now());
        metaObject.setValue("updateTime",LocalDateTime.now());

        metaObject.setValue("createUser",BaseContext.getCurrentId());
        metaObject.setValue("updateUser",BaseContext.getCurrentId());
    }
    @Override
    public void updateFill(MetaObject metaObject){
        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("updateUser", BaseContext.getCurrentId());
    }

}

这里有一个方法调用,为 BaseContext.getCurrentId(),该调用是为了满足动态获取用户 ID 的需求,为了实现这一需求,编写工具类 BaseContext,该工具类使用了 ThreadLocal

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h9yIB8yI-1657719042134)(单体项目-瑞吉外卖.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pyq5p2l5b6I6ZW_77yM5Yir5Y-q55yL55y85YmN,size_20,color_FFFFFF,t_70,g_se,x_16-20220711164756666.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JnHHRzyu-1657719042134)(单体项目-瑞吉外卖.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pyq5p2l5b6I6ZW_77yM5Yir5Y-q55yL55y85YmN,size_20,color_FFFFFF,t_70,g_se,x_16-20220711164801653.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vunpGq3A-1657719042135)(单体项目-瑞吉外卖.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pyq5p2l5b6I6ZW_77yM5Yir5Y-q55yL55y85YmN,size_20,color_FFFFFF,t_70,g_se,x_16-20220711164817836.png)]

然后为了动态的获取员工的id,这里我们使用了threadLocal这个局部变量来获取和存储员工id;

创建一个工具类来设置和获取threadLocal中的员工id, 注意:要先把数据设置进threadLocal中,才能获取到

package com.heyu.reggie.utils;
/*
 *@description: 基于 ThreadLocal 封装工具类,用户保存和获取当前登录用户的 id
 *@createTime:2022/7/11 16:22
 *@author:heyu
*/
public class BaseContext {
    private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
    /*
      * @description:设置值
      * @author: heyu
      * @date: 2022/7/11 16:24
      * @Param: null
      * @return:
     **/
    public static void setCurrentId(Long id){
        threadLocal.set(id);
    }

    public static Long getCurrentId(){
        return threadLocal.get();
    }

}

同时在前面的过滤器中也进行配置—LoginCheckFilter

//4、判断登录状态,如果已登录,则直接放行
        if(request.getSession().getAttribute("employee") != null){
            //log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("employee"));
            //把用户id存储到本地的threadLocal
            Long emId = (Long) request.getSession().getAttribute("employee");
            BaseContext.setCurrentId(emId);

            filterChain.doFilter(request,response);
            return;
        }

新增分类(菜品和套餐)

需求分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zsz0v1Yh-1657719042135)(单体项目-瑞吉外卖.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pyq5p2l5b6I6ZW_77yM5Yir5Y-q55yL55y85YmN,size_20,color_FFFFFF,t_70,g_se,x_16-20220711170333596.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xWeqgGQe-1657719042135)(单体项目-瑞吉外卖.assets/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pyq5p2l5b6I6ZW_77yM5Yir5Y-q55yL55y85YmN,size_20,color_FFFFFF,t_70,g_se,x_16-20220711170341342.png)]

数据模型

本模块需要用到的类和接口基本结构如下

1. 实体类 Category
2. Mapper接口 CategoryMapper
3. 业务层接口 CategoryService
4. 业务层实现类 CategoryServiceImpl
5. 控制层 CategoryController

创建实体类 Category

package com.heyu.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 Category implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;


    //类型 1 菜品分类 2 套餐分类
    private Integer type;


    //分类名称
    private String name;


    //顺序
    private Integer sort;


    //创建时间
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;


    //更新时间
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;


    //创建人
    @TableField(fill = FieldFill.INSERT)
    private Long createUser;


    //修改人
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;


    //是否删除
    private Integer isDeleted;

}


Day05

新增分类-菜品/套餐

代码开发

创建 CategoryController

首先创建添加菜品 API

@Slf4j
@RestController
@RequestMapping("/category")
public class CategoryController {
    @Autowired
    CategoryService categoryService;
    /*
      * @description:新增分类
      * @author: heyu
      * @date: 2022/7/12 09:19
      * @Param: null
      * @return: R
     **/
    @PostMapping
    public R<String> save(@RequestBody Category category){
        log.info("category:{}",category);
        categoryService.save(category);
        return R.success("新增分类成功");
    }
}

进行测试,我们选择

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RehWwftU-1657719042136)(单体项目-瑞吉外卖.assets/image-20220712092510889.png)]

川菜在数据库中已经存在,所以显示为:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5pkj48Vb-1657719042136)(单体项目-瑞吉外卖.assets/image-20220712092601713.png)]

这个已存在的错误提示,来自于全局异常处理 GlobalExceptionHandler,因为控制台输入了以下错误

2022-07-12 09:25:54.287 ERROR 3117 --- [nio-8090-exec-1] c.h.r.common.GlobalExceptionHandler      : Duplicate entry '川菜' for key 'category.idx_category_name'
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /*
     * @description:处理
     * @author: heyu 
     * @date: 2022-7-10 
     * @param:
     * @return: 
     **/
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public R<String> exceptionHandler(SQLIntegrityConstraintViolationException e){
        log.error(e.getMessage());
        if (e.getMessage().contains("Duplicate entry")){
            String[] split = e.getMessage().split(" ");
            String msg = split[2]+"已存在";
            return R.error(msg);
        }
        return R.error("未知错误");
    }
}

分类信息分页查询

需求分析

系统重的分类很多的时候,如果在一个页面中全部显示出来会比较乱,采用分页展示列表数据

代码开发

  1. 页面发送 Ajax 请求,将分页查询参数(page,PageSize,name)提交到服务端
  2. 服务端 Controller 接收页面提交的数据并调用 Service 查询数据
  3. Service 调用 Mapper 操作数据库,查询分页数据
  4. Controller 将查询到的分页数据,转为 JSON,响应给页面
  5. 页面接收到分页数据并通过 ElementUI 的 Table 组件展示到页面上
    /*
     * @description: 分页查询
     * @author: heyu
     * @date: 2022/7/12 09:33
     * @Param: page pageSize
     * @return:
     **/
    @GetMapping("/page")
    public R<Page> page(int page, int pageSize){
        //分页构造器
        Page<Category> pageInfo = new Page<>(page,pageSize);
        //创建一个条件构造器,用来排序,需要使用泛型来实现
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        //添加排序条件,根据 sort 字段进行排序
        wrapper.orderByAsc(Category::getSort);
        categoryService.page(pageInfo,wrapper);
        return R.success(pageInfo);
    }
}

删除分类

需求分析

在分类管理列表中,可以对某个分类进行删除,需要注意的是当分类关联了菜品或者套餐时,此分类不允许被删除

代码开发

  1. 页面发送 Ajax 请求,将参数 id 提交到服务端
  2. 服务端 Controller 接收页面提交的数据并调用 Service 删除数据
  3. Service 调用 Mapper 操作数据库

创建实体类、Mapper、Service、ServiceImpl和对应的 Controller

Dish

package com.heyu.reggie.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 菜品
 */
@Data
public class Dish implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;


    //菜品名称
    private String name;


    //菜品分类id
    private Long categoryId;


    //菜品价格
    private BigDecimal price;


    //商品码
    private String code;


    //图片
    private String image;


    //描述信息
    private String description;


    //0 停售 1 起售
    private Integer status;


    //顺序
    private Integer sort;


    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;


    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;


    @TableField(fill = FieldFill.INSERT)
    private Long createUser;


    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;


    //是否删除
    private Integer isDeleted;

}

SetMeal

package com.heyu.reggie.entity;


import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 套餐
 */
@Data
public class SetMeal implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;


    //分类id
    private Long categoryId;


    //套餐名称
    private String name;


    //套餐价格
    private BigDecimal price;


    //状态 0:停用 1:启用
    private Integer status;


    //编码
    private String code;


    //描述信息
    private String description;


    //图片
    private String image;


    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;


    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;


    @TableField(fill = FieldFill.INSERT)
    private Long createUser;


    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;


    //是否删除
    private Integer isDeleted;
}

DishMapper

package com.heyu.reggie.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fasterxml.jackson.databind.ser.Serializers;
import com.heyu.reggie.entity.Category;
import com.heyu.reggie.entity.Dish;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface DishMapper extends BaseMapper<Dish> {

}

SetMealMapper

package com.heyu.reggie.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.heyu.reggie.entity.SetMeal;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface SetMealMapper extends BaseMapper<SetMeal> {
}

DishService

package com.heyu.reggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.heyu.reggie.entity.Dish;

public interface DishService extends IService<Dish> {
}

SetMealService

package com.heyu.reggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.heyu.reggie.entity.SetMeal;

public interface SetMealService extends IService<SetMeal> {
}

DishServiceImpl

package com.heyu.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heyu.reggie.entity.Dish;
import com.heyu.reggie.mapper.DishMapper;
import com.heyu.reggie.service.DishService;
import org.springframework.stereotype.Service;

@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {
}

SetMealServiceImpl

package com.heyu.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heyu.reggie.entity.SetMeal;
import com.heyu.reggie.mapper.SetMealMapper;
import com.heyu.reggie.service.SetMealService;
import org.springframework.stereotype.Service;

@Service
public class SetMealServiceImpl extends ServiceImpl<SetMealMapper, SetMeal> implements SetMealService {
}

在 CategoryServiceImpl 中编写实现逻辑

@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService  {
    @Autowired
    DishService dishService;
    @Autowired
    SetMealService setMealService;


    @Override
    public void remove(Long id){
        //查询当前分类是否关联了菜品,如果已经关联了,抛出异常
        LambdaQueryWrapper<Dish> dishQueryWrapper = new LambdaQueryWrapper<>();
        //添加查询条件,根据用户 id进行查询
        dishQueryWrapper.eq(Dish::getCategoryId,id);
        int count_Dish = dishService.count(dishQueryWrapper);
        if (count_Dish>0){
            throw new CustomException("当前分类下关联了菜品,不能删除");
        }
        //查询当前分类是否关联了套餐,如果已经关联了,抛出异常
        LambdaQueryWrapper<SetMeal> setMealLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //添加查询条件,根据 ID 进行查询
        setMealLambdaQueryWrapper.eq(SetMeal::getCategoryId,id);
        int count_SetMeal = setMealService.count(setMealLambdaQueryWrapper);
        //正常删除分类
        if (count_SetMeal>0){
            throw new CustomException("当前分类下关联了套餐,不能删除");
        }
        super.removeById(id);
    }
}

同时需要处理异常信息,抛出这种异常,先自定义异常 CustomException

package com.heyu.reggie.common;

public class CustomException extends RuntimeException{
    public CustomException(String message){
        super(message);
    }
}

将其纳入全局异常处理器管理异常

@ExceptionHandler({CustomException.class})
public R<String> exceptionHandler(CustomException customException){
    log.error(customException.getMessage());//将报错信息打印到日志
    //这里拿到的 message 是业务类抛出的异常,我们把它显示到前端
    return R.error(customException.getMessage());
}

文件上传和下载

文件上传

文件上传对页面的 form 表单有要求为:

method = “post” 采用 post 方式提交数据

enctype = “multipart/form-data 采用 multipart 格式上传文件

type = “file” 使用 input 的 file控件上传

<form method ="post" action="/common/upload"enctype="multipart/form-data">
	<input name="myFile" type="file"/>
	<input type="submit" value="提交"/>
</form>	

服务端需要使用 Apache 的两个组件

common-fileupload

commons-io

Spring框架在 Spring-web 包中对文件上传进行了封装,大大简化了服务端代码,我们只需要在 Controller 的方法中声明一个 MulitpartFile 类型的参数即可接收上传的文件

文件下载

下载完成的两种表现:

以附件形式下载,弹出保存对话框,将文件保存到指定目录

直接在浏览器打开

新增菜品

需求分析

后台系统重可以管理菜品信息,通过新增功能来添加一个新的菜品,在添加菜品时需要选择当前菜品所属的菜品分裂,并且需要上传菜品图片,在移动端会按照菜品分类来展示对应的菜品信息

数据模型

新增菜品,其实就是将新增页面录入的菜品信息插入到 dish 表,如果添加了口味作法,还需要向 dish_flavor表插入数据,新增菜品这一功能涉及到两个表:

dish————————————-dish_flavor

代码开发

实体类 DishFlavor

package com.heyu.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 DishFlavor implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;


    //菜品id
    private Long dishId;


    //口味名称
    private String name;


    //口味数据list
    private String value;


    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;


    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;


    @TableField(fill = FieldFill.INSERT)
    private Long createUser;


    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;


    //是否删除
    private Integer isDeleted;

}

Mapper接口 DishFlavorMapper

@Mapper
public interface DishFlavorMapper extends BaseMapper<DishFlavor> {
}

业务层接口 DishFlavorService

public interface DishFlavorService extends IService<DishFlavor> {

}

业务层实现类 DishFlavorServiceImpl

@Service
public class DishFlavorServiceImpl extends ServiceImpl<DishFlavorMapper, DishFlavor> implements DishFlavorService {
}

控制层 DishController

@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {
    @Autowired
    DishFlavorService dishFlavorService;
    @Autowired
    DishService dishService;

    @PostMapping
    public R<String> save(@RequestBody DishDto dishDto){
        dishService.saveWithFlavor(dishDto);
        return R.success("新增菜品成功");
    }
}

DishServiceImpl

@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {

    @Autowired
    DishFlavorService dishFlavorService;



    @Override
    @Transactional
    public void saveWithFlavor(DishDto dishDto){
        //保存菜品的基本信息到菜品表 dish
        this.save(dishDto);//只保存基本信息到dish 表
        //需要获得菜品的 ID,这个 ID 在之前就已经获得了
        Long dishId = dishDto.getId();

        //菜品口味处理
        List<DishFlavor> flavors = dishDto.getFlavors();
        flavors = flavors.stream().map((item)->{
                     item.setDishId(dishId);
                     return item;
                    }).collect(Collectors.toList());//重新转回为 list 对象
        //保存菜品口味数据到菜品口味表 dish_flavor,因为口味有多条,采用批处理的方式
        dishFlavorService.saveBatch(dishDto.getFlavors());
    }
}

Day06

菜品信息分页查询

@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> queryWrapper = new LambdaQueryWrapper<>();
    //添加过滤条件,根据name进行查询
    queryWrapper.like(name!=null,Dish::getName,name);
    //添加排序条件
    queryWrapper.orderByDesc(Dish::getUpdateTime);
    dishService.page(pageInfo,queryWrapper);

    //对象拷贝,records属性不拷贝,单独拿出 record的 list 集合
    BeanUtils.copyProperties(pageInfo,dishDtoPage,"records");

    List<Dish> records = pageInfo.getRecords();
    List<DishDto> list = records.stream().map((item) -> {
        DishDto dishDto = new DishDto();
        //对象拷贝,从 item 到 dishDto
        BeanUtils.copyProperties(item, dishDto);
        //拿到每个菜品的分类 id
        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);
}

修改菜品

修改菜品的 Controller 页面

/*
  * @description: 修改菜品
  * @author: heyu 
  * @date: 2022/7/13 14:48
  * @Param: dishDtp
  * @return: R
 **/
@PutMapping
public R<String> update(@RequestBody DishDto dishDto){
    dishService.updateWithFlavor(dishDto);
    return R.success("菜品更新成功");
}

在 DishService 接口中 编写方法 updateWithFlavor,这一方法用于更新菜品信息,同时更新对应的口味

void updateWithFlavor(DishDto dishDto);

在对应实现类中实现该方法

@Override
@Transactional
public void updateWithFlavor(DishDto dishDto){
    //更新 dish表和flavor 表
    this.updateById(dishDto);
    //先清理当前菜品对应的口味数据------dish_flavor表执行 delete操作
    LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(DishFlavor::getDishId,dishDto.getId());
    dishFlavorService.remove(queryWrapper);
    //添加当前提交过来的口味数据-------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);

}

新增套餐

需求分析

通过新增套餐功能来添加一个新的套餐,在添加套餐时需要选择当前套餐所属的套餐分类和包含的菜品,并且需要上传套餐对应的图片,在移动端会按照 套餐分类来展示对应的套餐

数据模型

将新增页面录入的套餐信息插入到 setmeal表,还需要向 setmeal_dish表插入套餐和菜品关联数据

主要涉及两个表 setmeal ————套餐表 setmeal_dish———————-套餐菜品关系表

代码开发

实体类 SetmealDish

@Data
public class SetmealDish implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;


    //套餐id
    private Long setmealId;


    //菜品id
    private Long dishId;


    //菜品名称 (冗余字段)
    private String name;

    //菜品原价
    private BigDecimal price;

    //份数
    private Integer copies;


    //排序
    private Integer sort;


    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;


    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;


    @TableField(fill = FieldFill.INSERT)
    private Long createUser;


    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;


    //是否删除
    private Integer isDeleted;
}

DTO SetmealDto

@Data
public class SetmealDto extends Setmeal {
    private List<SetmealDish> setmealDishes;

    private String categoryName;
}

Mapper setmealMapper

@Mapper
public interface SetmealMapper extends BaseMapper<Setmeal> {
}

Service setmealService

public interface SetmealService extends IService<Setmeal> {

    //新增套餐,需要同时保存套餐和菜品的关联关系
    void saveWithDish(SetmealDto setMealDto);
}

ServiceImpl setmealServiceImpl

@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {

    @Autowired
    SetmealDishService setMealDishService;


    @Override
    @Transactional
    public 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);
    }
}

控制层 SetmealController

@Slf4j
@RestController
@RequestMapping("/setmeal")
public class SetmealController {

    @Autowired
    SetmealDishService setMealDishService;

    @Autowired
    SetmealService setMealService;

    @PostMapping
    public R<String> save(@RequestBody SetmealDto setMealDto){
        log.info("测试:{}",setMealDto);
        setMealService.saveWithDish(setMealDto);


        return R.success("新增套餐成功");
    }
}

套餐信息分页查询

和前面的分页方法是相同的

代码开发

  1. 页面(backend/page/combo/list.html)发送 Ajax 请求,将分页查询参数(page,pageSize,name)提交到服务端,获取分页数据
  2. 页面发送请求,请求服务端进行图片下载,用于页面图片展示

分页查询直接通过 Controller 实现

/*
  * @description: 套餐分页查询
  * @author: heyu
  * @date: 2022/7/13 20:21
  * @Param: page\pageSize\name
  * @return: Page
 **/
@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> queryWrapper = new LambdaQueryWrapper<>();
    //添加查询条件,根据 name 进行 like 模糊查询
    queryWrapper.like(name!=null,Setmeal::getName,name);
    //添加排序条件,根据更新时间降序排列
    queryWrapper.orderByDesc(Setmeal::getUpdateTime);
    setMealService.page(pageInfo,queryWrapper);

    //对象拷贝,records 代表分页的列表数据,因为泛型不一样,所以把 records 忽略
    BeanUtils.copyProperties(pageInfo,dtoPage,"records");
    List<Setmeal> records = pageInfo.getRecords();
    //可以理解为一个增强型 for 循环,item 为迭代,表示每一个分类数据
    List<SetmealDto> list=records.stream().map((item)->{
        SetmealDto setmealDto = new SetmealDto();
        //对 setmealDto 进行除 CategoryName之外的属性拷贝,这是因为 item 对象中没有这一属性
        BeanUtils.copyProperties(item,setmealDto);

        //获取分类 id , 通过 ID 获取分类对象,然后再通过分类对象获取分类名
        Long categoryId = item.getCategoryId();
        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);
}

删除套餐

setmealService方法

void deleteWithDish(List<Long> ids);

setmealServiceImpl

@Override
public void deleteWithDish(List<Long> ids){
    LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.in(Setmeal::getId,ids);
    queryWrapper.eq(Setmeal::getStatus,1);
    int count = this.count(queryWrapper);
    //如果不能删除,就抛出一个业务异常
    if(count>0){
        throw new CustomException("套餐正在售卖中,不能删除");
    }
    //如果可以删除,先删除套餐表中的数据
    this.removeByIds(ids);
    //删除关系表(setmeal_dish)中的数据
    LambdaQueryWrapper<SetmealDish> wrapper = new LambdaQueryWrapper<>();
    wrapper.in(SetmealDish::getSetmealId,ids);
    setMealDishService.remove(wrapper);
}

controller

@DeleteMapping
public R<String> delete(@RequestParam List<Long> ids){
    setMealService.deleteWithDish(ids);
    return R.success("套餐删除成功");
}
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-07-21 21:22:54  更:2022-07-21 21:23:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:17:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码