学习目标
1、完成区域管理开发
2、完成桌台管理开发
3、完成分类管理开发
4、完成菜品管理开发
第一章 商家平台-区域管理
在商家用户建立品牌、门店、员工后,就需要对当前的门店划分区域,每个门店都可以维护自己的餐厅区域,注意的桌台的数据归属我们采用多租户功能区实现这里不需要考虑【多租户】后面有专题去简介
1、功能区拆解

红色区域:此处为查询条件功能区,筛选列表信息
| 功能 | 说明 |
|---|---|
| 区域名称 | 输入区域名称,键盘按enter触发搜索列表 |
| 状态 | 下拉框,显示【启用、禁用】,change触发搜索列表 |
蓝色区域:区域维护功能
| 功能 | 说明 |
|---|---|
| 添加 | 新增区域信息 |
| 修改 | 修改区域信息 |
| 删除 | 删除区域信息==【真实删除】==,删除时,会有再次确认提示 |
| 禁用、启用 | 禁用启用区域 |
2、数据库结构
CREATE TABLE `tab_table_area` (`id` bigint(18) NOT NULL COMMENT '桌台区域id',`area_name` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '区域名称',`created_time` datetime DEFAULT NULL COMMENT '创建时间',`updated_time` datetime DEFAULT NULL COMMENT '创建时间',`sharding_id` bigint(18) DEFAULT NULL COMMENT '分库id',`store_id` bigint(18) NOT NULL COMMENT '门店主键id',`enterprise_id` bigint(18) NOT NULL COMMENT '商户号',`sort_no` int(11) DEFAULT NULL COMMENT '排序',`enable_flag` varchar(10) CHARACTER SET utf8 NOT NULL COMMENT '是否有效',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='桌台区域';
自动填充:
下列字段,无需手动填充,系统会自动填充下列字段
| 字段 | 注释 | 填充方式 |
|---|---|---|
| id | 主键 | 雪花算法 |
| enterprise_id | 商户号 | mybatis-plus-多租户拦截 |
| created_time | 创建时间 | mybatis-plus-自动填充组件 |
| updated_time | 修改时间 | mybatis-plus-自动填充组件 |
| sharding_id | 分库id | mybatis-plus-自动填充组件 |
| store_id | 门店id | mybatis-plus-多租户拦截 |
3、功能开发
在开始业务开发之前,我们首先看一下区域管理的UML图

TableAreaController:对TableAreaFace接口进行dubbo的RPC调用,为dubbo服务的消费者
TableAreaFace:区域管理dubbo接口定义
TableAreaFaceImpl:区域管理dubbo接口定义实现,这里做VO和POJO的转换
ITableAreaService:区域管理的业务接口定义,为TableAreaFaceImpl提供核心业务逻辑的定义
TableAreaServiceImpl:区域管理的业务接口定义实现
3.1、TableAreaFace接口
TableAreaFace:区域管理dubbo接口定义
package com.itheima.restkeeper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.exception.ProjectException;import com.itheima.restkeeper.req.TableAreaVo;import java.util.List;/*** @ClassName TableAreaFace.java* @Description 桌台区域dubbo服务*/public interface TableAreaFace {/*** @param tableAreaVo 查询条件* @param pageNum 当前页* @param pageSize 每页大小* @return Page<TableAreaVo>* @Description 区域列表*/Page<TableAreaVo> findTableAreaVoPage(TableAreaVo tableAreaVo,int pageNum,int pageSize)throws ProjectException;/*** @param tableAreaVo 对象信息* @return TableAreaVo* @Description 创建区域*/TableAreaVo createTableArea(TableAreaVo tableAreaVo)throws ProjectException;/*** @param tableAreaVo 对象信息* @return Boolean* @Description 修改区域*/Boolean updateTableArea(TableAreaVo tableAreaVo)throws ProjectException;/*** @param checkedIds 选择对象信息Id* @return Boolean* @Description 删除区域*/Boolean deleteTableArea(String[] checkedIds)throws ProjectException;/*** @param tableAreaId 选择对象信息Id* @return TableAreaVo* @Description 查找区域*/TableAreaVo findTableAreaByTableAreaId(Long tableAreaId)throws ProjectException;/**** @description 查询区域下拉框* @return: List<TableAreaVo>*/List<TableAreaVo> findTableAreaVoList()throws ProjectException;}
3.2、TableAreaFaceImpl接口实现
TableAreaFaceImpl:区域管理dubbo接口定义实现,这里做VO和POJO的转换
package com.itheima.restkeeper.face;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.TableAreaFace;import com.itheima.restkeeper.enums.TableAreaEnum;import com.itheima.restkeeper.exception.ProjectException;import com.itheima.restkeeper.pojo.TableArea;import com.itheima.restkeeper.req.TableAreaVo;import com.itheima.restkeeper.service.ITableAreaService;import com.itheima.restkeeper.utils.BeanConv;import com.itheima.restkeeper.utils.EmptyUtil;import com.itheima.restkeeper.utils.ExceptionsUtil;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.config.annotation.DubboService;import org.apache.dubbo.config.annotation.Method;import org.springframework.beans.factory.annotation.Autowired;import java.util.List;/*** @ClassName TableAreaFaceImpl.java* @Description 桌台区域dubbo服务*/@Slf4j@DubboService(version = "${dubbo.application.version}",timeout = 5000,methods ={@Method(name = "findTableAreaVoPage",retries = 2),@Method(name = "createTableArea",retries = 0),@Method(name = "updateTableArea",retries = 0),@Method(name = "deleteTableArea",retries = 0)})public class TableAreaFaceImpl implements TableAreaFace {@AutowiredITableAreaService tableAreaService;@Overridepublic Page<TableAreaVo> findTableAreaVoPage(TableAreaVo tableAreaVo,int pageNum,int pageSize)throws ProjectException {try {//查询区域分页Page<TableArea> page = tableAreaService.findTableAreaVoPage(tableAreaVo, pageNum, pageSize);Page<TableAreaVo> pageVo = new Page<>();BeanConv.toBean(page,pageVo);//结果集转换List<TableArea> tableAreaList = page.getRecords();List<TableAreaVo> tableAreaVoList = BeanConv.toBeanList(tableAreaList,TableAreaVo.class);pageVo.setRecords(tableAreaVoList);//返回结果return pageVo;} catch (Exception e) {log.error("查询区域列表异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(TableAreaEnum.PAGE_FAIL);}}@Overridepublic TableAreaVo createTableArea(TableAreaVo tableAreaVo) throws ProjectException{try {//创建区域return BeanConv.toBean( tableAreaService.createTableArea(tableAreaVo), TableAreaVo.class);} catch (Exception e) {log.error("保存区域异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(TableAreaEnum.CREATE_FAIL);}}@Overridepublic Boolean updateTableArea(TableAreaVo tableAreaVo) throws ProjectException{try {//修改区域return tableAreaService.updateTableArea(tableAreaVo);} catch (Exception e) {log.error("保存区域异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(TableAreaEnum.UPDATE_FAIL);}}@Overridepublic Boolean deleteTableArea(String[] checkedIds)throws ProjectException {try {//删除区域return tableAreaService.deleteTableArea(checkedIds);} catch (Exception e) {log.error("删除区域异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(TableAreaEnum.DELETE_FAIL);}}@Overridepublic TableAreaVo findTableAreaByTableAreaId(Long tableAreaId)throws ProjectException {try {//按id查询区域TableArea tableArea = tableAreaService.getById(tableAreaId);if (!EmptyUtil.isNullOrEmpty(tableArea)){return BeanConv.toBean(tableArea,TableAreaVo.class);}return null;} catch (Exception e) {log.error("查找区域所有区域异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(TableAreaEnum.SELECT_AREA_FAIL);}}@Overridepublic List<TableAreaVo> findTableAreaVoList()throws ProjectException {try {//查询区域return BeanConv.toBeanList(tableAreaService.findTableAreaVoList(),TableAreaVo.class);} catch (Exception e) {log.error("查找区域所有区域异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(TableAreaEnum.SELECT_AREA_LIST_FAIL);}}}
3.3、ITableAreaService业务接口
ITableAreaService:区域管理的业务接口定义,为TableAreaFaceImpl提供核心业务逻辑的定义
package com.itheima.restkeeper.service;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.pojo.TableArea;import com.itheima.restkeeper.pojo.TableArea;import com.baomidou.mybatisplus.extension.service.IService;import com.itheima.restkeeper.req.TableAreaVo;import java.util.List;/*** @Description:桌台区域 服务类*/public interface ITableAreaService extends IService<TableArea> {/*** @Description 区域列表* @param tableAreaVo 查询条件* @param pageNum 当前页* @param pageSize 每页大小* @return Page<TableArea>*/Page<TableArea> findTableAreaVoPage(TableAreaVo tableAreaVo, int pageNum, int pageSize);/*** @Description 创建区域* @param tableAreaVo 对象信息* @return TableArea*/TableArea createTableArea(TableAreaVo tableAreaVo);/*** @Description 修改区域* @param tableAreaVo 对象信息* @return Boolean*/Boolean updateTableArea(TableAreaVo tableAreaVo);/*** @Description 删除区域* @param checkedIds 选择的区域ID* @return Boolean*/Boolean deleteTableArea(String[] checkedIds);/**** @description 查询区域下拉框* @return: List<TableArea>*/List<TableArea> findTableAreaVoList();}
3.4、TableAreaServiceImpl接口实现
TableAreaServiceImpl:区域管理的业务接口定义实现
package com.itheima.restkeeper.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.itheima.restkeeper.basic.BasicPojo;import com.itheima.restkeeper.constant.SuperConstant;import com.itheima.restkeeper.mapper.TableAreaMapper;import com.itheima.restkeeper.pojo.TableArea;import com.itheima.restkeeper.req.TableAreaVo;import com.itheima.restkeeper.service.ITableAreaService;import com.itheima.restkeeper.utils.BeanConv;import com.itheima.restkeeper.utils.EmptyUtil;import org.springframework.stereotype.Service;import java.util.ArrayList;import java.util.Arrays;import java.util.List;/*** @Description:桌台区域 服务实现类*/@Servicepublic class TableAreaServiceImpl extends ServiceImpl<TableAreaMapper, TableArea> implements ITableAreaService {@Overridepublic Page<TableArea> findTableAreaVoPage(TableAreaVo tableAreaVo, int pageNum, int pageSize) {//构建分页对象Page<TableArea> page = new Page<>(pageNum,pageSize);QueryWrapper<TableArea> queryWrapper = new QueryWrapper<>();//按区域名称查询if (!EmptyUtil.isNullOrEmpty(tableAreaVo.getAreaName())) {queryWrapper.lambda().likeRight(TableArea::getAreaName,tableAreaVo.getAreaName());}//按是否有效查询if (!EmptyUtil.isNullOrEmpty(tableAreaVo.getEnableFlag())) {queryWrapper.lambda().eq(TableArea::getEnableFlag,tableAreaVo.getEnableFlag());}//按sortNo升序排列queryWrapper.lambda().orderByAsc(TableArea::getSortNo);//返回结果return page(page, queryWrapper);}@Overridepublic TableArea createTableArea(TableAreaVo tableAreaVo) {//转换TableAreaVo为TableAreaTableArea tableArea = BeanConv.toBean(tableAreaVo, TableArea.class);//执行保存boolean flag = save(tableArea);if (flag){return tableArea;}return null;}@Overridepublic Boolean updateTableArea(TableAreaVo tableAreaVo) {//转换TableAreaVo为TableAreaTableArea tableArea = BeanConv.toBean(tableAreaVo, TableArea.class);//按ID执行修改return updateById(tableArea);}@Overridepublic Boolean deleteTableArea(String[] checkedIds) {//构建选中的List<Sring>集合List<String> ids = Arrays.asList(checkedIds);List<Long> idsLong = new ArrayList<>();ids.forEach(n->{idsLong.add(Long.valueOf(n));});//批量删除return removeByIds(idsLong);}@Overridepublic List<TableArea> findTableAreaVoList() {//构建查询条件QueryWrapper<TableArea> queryWrapper = new QueryWrapper<>();queryWrapper.lambda().eq(BasicPojo::getEnableFlag, SuperConstant.YES);//执行list查询return list(queryWrapper);}}
3.5、TableAreaController类
TableAreaController:对TableAreaFace接口进行dubbo的RPC调用,为dubbo服务的消费者
package com.itheima.restkeeper.web;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.TableAreaFace;import com.itheima.restkeeper.basic.ResponseWrap;import com.itheima.restkeeper.enums.TableAreaEnum;import com.itheima.restkeeper.exception.ProjectException;import com.itheima.restkeeper.req.TableAreaVo;import com.itheima.restkeeper.utils.EmptyUtil;import com.itheima.restkeeper.utils.ExceptionsUtil;import com.itheima.restkeeper.utils.ResponseWrapBuild;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiImplicitParams;import io.swagger.annotations.ApiOperation;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.config.annotation.DubboReference;import org.springframework.validation.annotation.Validated;import org.springframework.web.bind.annotation.*;import java.util.List;/*** @ClassName TableAreaController.java* @Description 区域Controller*/@RestController@RequestMapping("table-area")@Slf4j@Api(tags = "区域controller")public class TableAreaController {@DubboReference(version = "${dubbo.application.version}",check = false)TableAreaFace tableAreaFace;/*** @Description 区域列表* @param tableAreaVo 查询条件* @return*/@PostMapping("page/{pageNum}/{pageSize}")@ApiOperation(value = "查询区域分页",notes = "查询区域分页")@ApiImplicitParams({@ApiImplicitParam(name = "tableAreaVo",value = "区域查询对象",dataType = "TableAreaVo"),@ApiImplicitParam(paramType = "path",name = "pageNum",value = "页码",dataType = "Integer"),@ApiImplicitParam(paramType = "path",name = "pageSize",value = "每页条数",dataType = "Integer")})public ResponseWrap<Page<TableAreaVo>> findTableAreaVoPage(@RequestBody TableAreaVo tableAreaVo,@PathVariable("pageNum") int pageNum,@PathVariable("pageSize") int pageSize) {Page<TableAreaVo> tableAreaVoPage = tableAreaFace.findTableAreaVoPage(tableAreaVo, pageNum, pageSize);return ResponseWrapBuild.build(TableAreaEnum.SUCCEED,tableAreaVoPage);}/*** @Description 添加区域* @param tableAreaVo 对象信息* @return*/@PostMapping@ApiOperation(value = "添加区域",notes = "添加区域")@ApiImplicitParam(name = "tableAreaVo",value = "区域对象",required = true,dataType = "TableAreaVo")ResponseWrap<TableAreaVo> createTableArea(@RequestBody TableAreaVo tableAreaVo) {TableAreaVo tableAreaVoResult = tableAreaFace.createTableArea(tableAreaVo);return ResponseWrapBuild.build(TableAreaEnum.SUCCEED,tableAreaVoResult);}/*** @Description 修改区域* @param tableAreaVo 对象信息* @return*/@PatchMapping@ApiOperation(value = "修改区域",notes = "修改区域")@ApiImplicitParam(name = "tableAreaVo",value = "区域对象",required = true,dataType = "TableAreaVo")ResponseWrap<Boolean> updateTableArea(@RequestBody TableAreaVo tableAreaVo) {Boolean flag = tableAreaFace.updateTableArea(tableAreaVo);return ResponseWrapBuild.build(TableAreaEnum.SUCCEED,flag);}/*** @Description 删除区域* @param tableAreaVo 查询对象* @return*/@DeleteMapping@ApiOperation(value = "删除区域",notes = "删除区域")@ApiImplicitParam(name = "tableAreaVo",value = "区域查询对象",required = true,dataType = "TableAreaVo")ResponseWrap<Boolean> deleteTableArea(@RequestBody TableAreaVo tableAreaVo ) {//获得所有选择的区域IDSString[] checkedIds = tableAreaVo.getCheckedIds();Boolean flag = tableAreaFace.deleteTableArea(checkedIds);return ResponseWrapBuild.build(TableAreaEnum.SUCCEED,flag);}/*** @Description 查找区域* @param tableAreaId 区域id* @return*/@GetMapping("{tableAreaId}")@ApiOperation(value = "查找区域",notes = "查找区域")@ApiImplicitParam(paramType = "path",name = "tableAreaId",value = "区域Id",example = "1",dataType = "Long")ResponseWrap<TableAreaVo> findTableAreaByTableAreaId(@PathVariable("tableAreaId") Long tableAreaId) {TableAreaVo tableAreaVo = tableAreaFace.findTableAreaByTableAreaId(tableAreaId);return ResponseWrapBuild.build(TableAreaEnum.SUCCEED, tableAreaVo);}/*** @Description 查找区域* @return*/@GetMapping("list")@ApiOperation(value = "查找区域列表",notes = "查找区域列表")ResponseWrap<List<TableAreaVo>> findTableAreaVoList() {List<TableAreaVo> list = tableAreaFace.findTableAreaVoList();return ResponseWrapBuild.build(TableAreaEnum.SUCCEED,list);}@PostMapping("update-tableArea-enableFlag")@ApiOperation(value = "修改区域状态",notes = "修改区域状态")ResponseWrap<Boolean> updateTableAreaEnableFlag(@RequestBody TableAreaVo tableAreaVo) {Boolean flag = tableAreaFace.updateTableArea(tableAreaVo);return ResponseWrapBuild.build(TableAreaEnum.SUCCEED,flag);}}
第二章 商家平台-桌台管理
商家建立区域后,需要为区域指定对于的桌台,桌台的就餐人数,以及各种状态【空闲、开桌、锁桌】等切换,注意的桌台的数据归属我们采用多租户功能区实现这里不需要考虑【多租户】后面有专题去简介

1、功能区拆解

红色区域:此处为查询条件功能区,筛选列表信息
| 功能 | 说明 |
|---|---|
| 桌台名称 | 输入桌台名称,键盘按enter触发搜索列表 |
| 就餐人数 | 输入就餐人数,键盘按enter触发搜索列 |
| 桌台状体 | 下拉框,显示【空闲、开台、锁桌】,change触发搜索列表 |
| 状态 | 下拉框,显示【启用、禁用】,change触发搜索列表 |
蓝色区域:桌台维护功能
| 功能 | 说明 |
|---|---|
| 添加 | 新增桌台信息 |
| 修改 | 修改桌台信息 |
| 删除 | 删除桌台信息==【真实删除】==,删除时,会有再次确认提示 |
| 禁用、启用 | 禁用启用桌台 |
| 空闲、锁台 | 切换桌台状态 |
2、数据库结构
CREATE TABLE `tab_table` (`id` bigint(18) NOT NULL COMMENT '桌台id',`area_id` bigint(18) DEFAULT NULL COMMENT '区域ID',`table_name` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '桌台名称',`table_seat_number` int(11) NOT NULL COMMENT '桌台座位数目',`table_status` varchar(32) COLLATE utf8_bin NOT NULL COMMENT 'FREE:空闲 USER:开桌 lOCK 锁桌',`created_time` datetime DEFAULT NULL COMMENT '创建时间',`updated_time` datetime DEFAULT NULL COMMENT '创建时间',`sharding_id` bigint(18) DEFAULT NULL COMMENT '分库id',`store_id` bigint(18) NOT NULL COMMENT '门店主键id',`enterprise_id` bigint(18) NOT NULL COMMENT '商户号',`sort_no` int(11) DEFAULT NULL COMMENT '排序',`enable_flag` varchar(10) CHARACTER SET utf8 NOT NULL COMMENT '是否有效',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='桌台';
自动填充:
下列字段,无需手动填充,系统会自动填充下列字段
| 字段 | 注释 | 填充方式 |
|---|---|---|
| id | 主键 | 雪花算法 |
| enterprise_id | 商户号 | mybatis-plus-多租户拦截 |
| created_time | 创建时间 | mybatis-plus-自动填充组件 |
| updated_time | 修改时间 | mybatis-plus-自动填充组件 |
| sharding_id | 分库id | mybatis-plus-自动填充组件 |
| store_id | 门店id | mybatis-plus-多租户拦截 |
3、功能开发

TableController:对TableFace接口进行dubbo的RPC调用,为dubbo服务的消费者
TableFace:桌台管理dubbo接口定义
TableFaceImpl:桌台管理dubbo接口定义实现,这里做VO和POJO的转换
ITableService:桌台管理的业务接口定义,为TableFaceImpl提供核心业务逻辑的定义
TableServiceImpl:桌台管理的业务接口定义实现
3.1、TableFace接口
桌台管理dubbo接口定义
package com.itheima.restkeeper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.exception.ProjectException;import com.itheima.restkeeper.req.TableVo;import java.util.List;/*** @Description 桌台dubbo接口服务*/public interface TableFace {/*** @param tableVo 查询条件* @param pageNum 当前页* @param pageSize 每页大小* @return* @Description 桌台列表*/Page<TableVo> findTableVoPage(TableVo tableVo,int pageNum,int pageSize)throws ProjectException;/*** @param tableVo 对象信息* @return TableVo* @Description 创建桌台*/TableVo createTable(TableVo tableVo)throws ProjectException;/*** @param tableVo 对象信息* @return Boolean* @Description 修改桌台*/Boolean updateTable(TableVo tableVo)throws ProjectException;/*** @param checkedIds 选择对象信息Id* @return Boolean* @Description 删除桌台*/Boolean deleteTable(String[] checkedIds)throws ProjectException;/*** @param tableId 选择对象信息Id* @return TableVo* @Description 查找桌台*/TableVo findTableByTableId(Long tableId)throws ProjectException;/**** @description 查询桌台下拉框* @return: List<TableVo>*/List<TableVo> findTableVoList()throws ProjectException;}
3.2、TableFaceImpl接口实现
桌台管理dubbo接口定义实现,这里做VO和POJO的转换
package com.itheima.restkeeper.face;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.TableFace;import com.itheima.restkeeper.enums.TableEnum;import com.itheima.restkeeper.exception.ProjectException;import com.itheima.restkeeper.pojo.Table;import com.itheima.restkeeper.req.TableVo;import com.itheima.restkeeper.service.ITableService;import com.itheima.restkeeper.utils.BeanConv;import com.itheima.restkeeper.utils.EmptyUtil;import com.itheima.restkeeper.utils.ExceptionsUtil;import com.itheima.restkeeper.utils.ResponseWrapBuild;import io.seata.spring.annotation.GlobalTransactional;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.config.annotation.DubboService;import org.apache.dubbo.config.annotation.Method;import org.springframework.beans.factory.annotation.Autowired;import java.util.List;/*** @Description 桌台dubbo接口实现*/@Slf4j@DubboService(version = "${dubbo.application.version}",timeout = 5000,methods ={@Method(name = "findTableVoPage",retries = 2),@Method(name = "createTable",retries = 0),@Method(name = "updateTable",retries = 0),@Method(name = "deleteTable",retries = 0)})public class TableFaceImpl implements TableFace {@AutowiredITableService tableService;@Overridepublic Page<TableVo> findTableVoPage(TableVo tableVo,int pageNum,int pageSize) throws ProjectException{try {//查询所有桌台Page<Table> page = tableService.findTableVoPage(tableVo, pageNum, pageSize);Page<TableVo> pageVo = new Page<>();BeanConv.toBean(page,pageVo);//结果集转换List<Table> tableList = page.getRecords();List<TableVo> tableVoList = BeanConv.toBeanList(tableList,TableVo.class);pageVo.setRecords(tableVoList);return pageVo;} catch (Exception e) {log.error("查询桌台列表异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(TableEnum.SELECT_TABLE_LIST_FAIL);}}@Overridepublic TableVo createTable(TableVo tableVo) throws ProjectException{try {//添加桌台return BeanConv.toBean( tableService.createTable(tableVo), TableVo.class);} catch (Exception e) {log.error("保存桌台异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(TableEnum.CREATE_FAIL);}}@Override@GlobalTransactionalpublic Boolean updateTable(TableVo tableVo) throws ProjectException{try {//修改桌台return tableService.updateTable(tableVo);} catch (Exception e) {log.error("保存桌台异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(TableEnum.UPDATE_FAIL);}}@Overridepublic Boolean deleteTable(String[] checkedIds) throws ProjectException{try {//删除桌台return tableService.deleteTable(checkedIds);} catch (Exception e) {log.error("删除桌台异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(TableEnum.DELETE_FAIL);}}@Overridepublic TableVo findTableByTableId(Long tableId)throws ProjectException {try {//按ID查询桌台Table table = tableService.getById(tableId);if (!EmptyUtil.isNullOrEmpty(table)){return BeanConv.toBean(table,TableVo.class);}return null;} catch (Exception e) {log.error("查找桌台所有桌台异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(TableEnum.SELECT_TABLE_FAIL);}}@Overridepublic List<TableVo> findTableVoList()throws ProjectException {try {//查询桌台列表,用在哪里?是否要注意状态return BeanConv.toBeanList(tableService.findTableVoList(),TableVo.class);} catch (Exception e) {log.error("查找桌台所有桌台异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(TableEnum.SELECT_TABLE_LIST_FAIL);}}}
3.3、ITableService业务接口
桌台管理的业务接口定义,为TableFaceImpl提供核心业务逻辑的定义
package com.itheima.restkeeper.service;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.baomidou.mybatisplus.extension.service.IService;import com.itheima.restkeeper.pojo.Table;import com.itheima.restkeeper.req.TableVo;import java.util.List;/*** @Description:桌台服务类*/public interface ITableService extends IService<Table> {/*** @param tableVo 查询条件* @param pageNum 当前页* @param pageSize 每页大小* @return Page<Table>* @Description 门店列表*/Page<Table> findTableVoPage(TableVo tableVo, int pageNum, int pageSize);/*** @param tableVo 对象信息* @return Table* @Description 创建门店*/Table createTable(TableVo tableVo);/*** @param tableVo 对象信息* @return Boolean* @Description 修改门店*/Boolean updateTable(TableVo tableVo);/*** @param checkedIds 选择的门店ID* @return Boolean* @Description 删除门店*/Boolean deleteTable(String[] checkedIds);/**** @description 查询门店下拉框* @return: List<Table>*/List<Table> findTableVoList();/**** @description 当桌台处于空闲状态,进行开桌* @param tableVo* @return*/Boolean openTable(TableVo tableVo);}
3.4、TableServiceImpl业务接口实现
桌台管理的业务接口定义实现
package com.itheima.restkeeper.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.basic.BasicPojo;import com.itheima.restkeeper.constant.SuperConstant;import com.itheima.restkeeper.pojo.Table;import com.itheima.restkeeper.mapper.TableMapper;import com.itheima.restkeeper.req.TableVo;import com.itheima.restkeeper.service.ITableService;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.itheima.restkeeper.utils.BeanConv;import com.itheima.restkeeper.utils.EmptyUtil;import org.springframework.stereotype.Service;import java.util.ArrayList;import java.util.Arrays;import java.util.List;/*** @Description:桌台 服务实现类*/@Servicepublic class TableServiceImpl extends ServiceImpl<TableMapper, Table> implements ITableService {@Overridepublic Page<Table> findTableVoPage(TableVo tableVo,int pageNum,int pageSize) {//构建分页对象Page<Table> page = new Page<>(pageNum,pageSize);QueryWrapper<Table> queryWrapper = new QueryWrapper<>();//按桌台名称查询if (!EmptyUtil.isNullOrEmpty(tableVo.getTableName())) {queryWrapper.lambda().likeRight(Table::getTableName,tableVo.getTableName());}//按就餐人数查询if (!EmptyUtil.isNullOrEmpty(tableVo.getTableSeatNumber())) {queryWrapper.lambda().eq(Table::getTableSeatNumber,tableVo.getTableSeatNumber());}//按桌台使用状态查询if (!EmptyUtil.isNullOrEmpty(tableVo.getTableStatus())) {queryWrapper.lambda().eq(Table::getTableStatus,tableVo.getTableStatus());}//按桌台有效性查询if (!EmptyUtil.isNullOrEmpty(tableVo.getEnableFlag())) {queryWrapper.lambda().eq(Table::getEnableFlag,tableVo.getEnableFlag());}//按sortNo升序排列queryWrapper.lambda().orderByAsc(Table::getSortNo);//返回分页结果return page(page,queryWrapper);}@Overridepublic Table createTable(TableVo tableVo) {//转换TableVo为TableTable table = BeanConv.toBean(tableVo, Table.class);//执行保存boolean flag = save(table);if (flag){return table;}return null;}@Overridepublic Boolean updateTable(TableVo tableVo) {//转换TableVo为TableTable table = BeanConv.toBean(tableVo, Table.class);//执行按ID进行修改return updateById(table);}@Overridepublic Boolean deleteTable(String[] checkedIds) {//构建选择ids的List<String>集合List<String> ids = Arrays.asList(checkedIds);List<Long> idsLong = new ArrayList<>();ids.forEach(n->{idsLong.add(Long.valueOf(n));});//执行批量移除return removeByIds(idsLong);}@Overridepublic List<Table> findTableVoList() {//构建查询条件:有效状态QueryWrapper<Table> queryWrapper = new QueryWrapper<>();queryWrapper.lambda().eq(BasicPojo::getEnableFlag, SuperConstant.YES);//执行list查询return list(queryWrapper);}@Overridepublic Boolean openTable(TableVo tableVo) {//构建条件:SuperConstant.FREELambdaQueryWrapper<Table> lambdaQueryWrapper = new LambdaQueryWrapper();lambdaQueryWrapper.eq(Table::getTableStatus,SuperConstant.FREE).eq(Table::getId,tableVo.getId());//执行update条件查询return update(BeanConv.toBean(tableVo,Table.class),lambdaQueryWrapper);}}
3.5、TableController类
对TableFace接口进行dubbo的RPC调用,为dubbo服务的消费者
package com.itheima.restkeeper.web;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.TableFace;import com.itheima.restkeeper.basic.ResponseWrap;import com.itheima.restkeeper.enums.TableEnum;import com.itheima.restkeeper.exception.ProjectException;import com.itheima.restkeeper.req.TableVo;import com.itheima.restkeeper.utils.EmptyUtil;import com.itheima.restkeeper.utils.ExceptionsUtil;import com.itheima.restkeeper.utils.ResponseWrapBuild;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiImplicitParams;import io.swagger.annotations.ApiOperation;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.config.annotation.DubboReference;import org.springframework.web.bind.annotation.*;import java.util.List;/*** @ClassName TableController.java* @Description 桌台Controller*/@RestController@RequestMapping("table")@Slf4j@Api(tags = "桌台controller")public class TableController {@DubboReference(version = "${dubbo.application.version}",check = false)TableFace tableFace;/*** @Description 桌台列表* @param tableVo 查询条件* @return*/@PostMapping("page/{pageNum}/{pageSize}")@ApiOperation(value = "查询桌台list",notes = "查询桌台list")@ApiImplicitParams({@ApiImplicitParam(name = "tableVo",value = "桌台查询对象",dataType = "TableVo"),@ApiImplicitParam(paramType = "path",name = "pageNum",value = "页码",dataType = "Integer"),@ApiImplicitParam(paramType = "path",name = "pageSize",value = "每页条数",dataType = "Integer")})public ResponseWrap<Page<TableVo>> findTableVoPage(@RequestBody TableVo tableVo,@PathVariable("pageNum") int pageNum,@PathVariable("pageSize") int pageSize) {Page<TableVo> tableVoList = tableFace.findTableVoPage(tableVo,pageNum,pageSize);return ResponseWrapBuild.build(TableEnum.SUCCEED,tableVoList);}/*** @Description 添加桌台* @param tableVo 对象信息* @return*/@PostMapping@ApiOperation(value = "添加桌台",notes = "添加桌台")@ApiImplicitParam(name = "tableVo",value = "桌台对象",required = true,dataType = "TableVo")ResponseWrap<TableVo> createTable(@RequestBody TableVo tableVo) {TableVo tableVoResult = tableFace.createTable(tableVo);return ResponseWrapBuild.build(TableEnum.SUCCEED,tableVoResult);}/*** @Description 修改桌台* @param tableVo 对象信息* @return*/@PatchMapping@ApiOperation(value = "修改桌台",notes = "修改桌台")@ApiImplicitParam(name = "tableVo",value = "桌台对象",required = true,dataType = "TableVo")ResponseWrap<Boolean> updateTable(@RequestBody TableVo tableVo) {Boolean flag = tableFace.updateTable(tableVo);return ResponseWrapBuild.build(TableEnum.SUCCEED,flag);}/*** @Description 查找桌台* @param tableId 桌台id* @return*/@GetMapping("{tableId}")@ApiOperation(value = "查找桌台",notes = "查找桌台")@ApiImplicitParam(paramType = "path",name = "tableId",value = "桌台Id",dataType = "Long")ResponseWrap<TableVo> findTableByTableId(@PathVariable("tableId") Long tableId) {TableVo tableVo = tableFace.findTableByTableId(tableId);return ResponseWrapBuild.build(TableEnum.SUCCEED,tableVo);}/*** @Description 删除桌台* @param tableVo 查询对象* @return*/@DeleteMapping@ApiOperation(value = "删除桌台",notes = "删除桌台")@ApiImplicitParam(name = "tableVo",value = "桌台查询对象",required = true,dataType = "TableVo")ResponseWrap<Boolean> deleteTable(@RequestBody TableVo tableVo ) {//拿到选中桌台的IDSString[] checkedIds = tableVo.getCheckedIds();Boolean flag = tableFace.deleteTable(checkedIds);return ResponseWrapBuild.build(TableEnum.SUCCEED,flag);}/*** @Description 查找桌台* @return*/@GetMapping("list")@ApiOperation(value = "查找桌台列表",notes = "查找桌台列表")ResponseWrap<List<TableVo>> findTableVoList() {List<TableVo> list = tableFace.findTableVoList();return ResponseWrapBuild.build(TableEnum.SUCCEED,list);}@PostMapping("update-table-enableFlag")@ApiOperation(value = "修改桌台有效状态",notes = "修改桌台有效状态")ResponseWrap<Boolean> updateTableEnableFlag(@RequestBody TableVo tableVo) {Boolean flag = tableFace.updateTable(tableVo);return ResponseWrapBuild.build(TableEnum.SUCCEED,flag);}@PostMapping("update-table-tableStatus")@ApiOperation(value = "修改桌台状态",notes = "修改桌台状态")ResponseWrap<Boolean> updateTableStatus(@RequestBody TableVo tableVo) {Boolean flag = tableFace.updateTable(tableVo);return ResponseWrapBuild.build(TableEnum.SUCCEED,flag);}}
第三章 商家平台-分类管理
菜品的分类主要是为菜品进行分类,在点餐的app端用户可以根据菜品分类去筛选菜品,帮助用户快速找到锁需要的菜品注意的分类的数据归属我们采用多租户功能区实现这里不需要考虑【多租户】后面有专题去简介

1、功能区拆解

红色区域:此处为查询条件功能区,筛选列表信息
| 功能 | 说明 |
|---|---|
| 分类名称 | 输入分类名称,键盘按enter触发搜索列表 |
| 状态 | 下拉框,显示【启用、禁用】,change触发搜索列表 |
蓝色区域:菜品分类维护功能
| 功能 | 说明 |
|---|---|
| 添加 | 新增分类信息 |
| 修改 | 修改分类信息 |
| 删除 | 删除分类信息==【真实删除】==,删除时,会有再次确认提示 |
| 禁用、启用 | 禁用启用分类 |

在添加或修改菜品分类时候,我们会从数字字典中获得分类类型【菜品、套餐】,用于区分是单个菜品还是套餐
2、数据库结构
CREATE TABLE `tab_category` (`id` bigint(18) NOT NULL COMMENT '分类id',`category_type` varchar(11) COLLATE utf8_bin DEFAULT NULL COMMENT '类型 菜品:DISH 套餐:MEAL',`category_name` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '分类名称',`enable_flag` varchar(18) CHARACTER SET utf8 DEFAULT NULL COMMENT '是否有效',`created_time` datetime DEFAULT NULL COMMENT '创建时间',`updated_time` datetime DEFAULT NULL COMMENT '创建时间',`sharding_id` bigint(18) DEFAULT NULL COMMENT '分库id',`store_id` bigint(18) NOT NULL COMMENT '门店主键id',`enterprise_id` bigint(18) NOT NULL COMMENT '商户号',`sort_no` int(11) DEFAULT NULL COMMENT '排序',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='菜品及套餐分类';
自动填充:
下列字段,无需手动填充,系统会自动填充下列字段
| 字段 | 注释 | 填充方式 |
|---|---|---|
| id | 主键 | 雪花算法 |
| enterprise_id | 商户号 | mybatis-plus-多租户拦截 |
| created_time | 创建时间 | mybatis-plus-自动填充组件 |
| updated_time | 修改时间 | mybatis-plus-自动填充组件 |
| sharding_id | 分库id | mybatis-plus-自动填充组件 |
| store_id | 门店id | mybatis-plus-多租户拦截 |
3、功能开发

CategoryController:对CategoryFace接口进行dubbo的RPC调用,为dubbo服务的消费者
CategoryFace:菜品分类管理dubbo接口定义
CategoryFaceImpl:菜品分类管理dubbo接口定义实现,这里做VO和POJO的转换
ICategoryService:菜品分类管理的业务接口定义,为CategoryFaceImpl提供核心业务逻辑的定义
CategoryServiceImpl:菜品分类管理的业务接口定义实现
3.1、CategoryFace接口
品分类管理dubbo接口定义
package com.itheima.restkeeper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.exception.ProjectException;import com.itheima.restkeeper.req.CategoryVo;import java.util.List;/*** @ClassName CategoryFace.java* @Description 菜品分类dubbo服务接口*/public interface CategoryFace {/*** @Description 分类列表* @param categoryVo 查询条件* @param pageNum 当前页* @param pageSize 每页条数* @return Page<CategoryVo>*/Page<CategoryVo> findCategoryVoPage(CategoryVo categoryVo,int pageNum,int pageSize)throws ProjectException;/*** @Description 创建分类* @param categoryVo 对象信息* @return CategoryVo*/CategoryVo createCategory(CategoryVo categoryVo)throws ProjectException;/*** @Description 修改分类* @param categoryVo 对象信息* @return Boolean*/Boolean updateCategory(CategoryVo categoryVo)throws ProjectException;/*** @Description 删除分类* @param checkedIds 选择对象信息Id* @return Boolean*/Boolean deleteCategory(String[] checkedIds)throws ProjectException;/*** @Description 查找分类* @param categoryId 选择对象信息Id* @return CategoryVo*/CategoryVo findCategoryByCategoryId(Long categoryId)throws ProjectException;/**** @description 查询分类下拉框* @return: List<CategoryVo>*/List<CategoryVo> findCategoryVoList()throws ProjectException;}
3.2、CategoryFaceImpl接口实现
菜品分类管理dubbo接口定义实现,这里做VO和POJO的转换
package com.itheima.restkeeper.face;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.CategoryFace;import com.itheima.restkeeper.enums.CategoryEnum;import com.itheima.restkeeper.exception.ProjectException;import com.itheima.restkeeper.pojo.Category;import com.itheima.restkeeper.req.CategoryVo;import com.itheima.restkeeper.service.ICategoryService;import com.itheima.restkeeper.utils.BeanConv;import com.itheima.restkeeper.utils.EmptyUtil;import com.itheima.restkeeper.utils.ExceptionsUtil;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.config.annotation.DubboService;import org.apache.dubbo.config.annotation.Method;import org.springframework.beans.factory.annotation.Autowired;import java.util.List;/*** @ClassName CategoryFaceImpl.java* @Description 菜品分类dubbo服务接口实现*/@Slf4j@DubboService(version = "${dubbo.application.version}",timeout = 5000,methods ={@Method(name = "findCategoryVoPage",retries = 2),@Method(name = "createCategory",retries = 0),@Method(name = "updateCategory",retries = 0),@Method(name = "deleteCategory",retries = 0)})public class CategoryFaceImpl implements CategoryFace {@AutowiredICategoryService categoryService;@Overridepublic Page<CategoryVo> findCategoryVoPage(CategoryVo categoryVo,int pageNum,int pageSize)throws ProjectException {try {//查询分类分页Page<Category> page = categoryService.findCategoryVoPage(categoryVo, pageNum, pageSize);Page<CategoryVo> pageVo = new Page<>();BeanConv.toBean(page,pageVo);//结果集转换List<Category> categoryList = page.getRecords();List<CategoryVo> categoryVoList = BeanConv.toBeanList(categoryList,CategoryVo.class);pageVo.setRecords(categoryVoList);//返回结果return pageVo;} catch (Exception e) {log.error("查询分类列表异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(CategoryEnum.PAGE_FAIL);}}@Overridepublic CategoryVo createCategory(CategoryVo categoryVo)throws ProjectException {try {//创建分类return BeanConv.toBean( categoryService.createCategory(categoryVo), CategoryVo.class);} catch (Exception e) {log.error("保存分类异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(CategoryEnum.CREATE_FAIL);}}@Overridepublic Boolean updateCategory(CategoryVo categoryVo) throws ProjectException{try {//修改分类return categoryService.updateCategory(categoryVo);} catch (Exception e) {log.error("保存分类异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(CategoryEnum.UPDATE_FAIL);}}@Overridepublic Boolean deleteCategory(String[] checkedIds) {try {//删除分类return categoryService.deleteCategory(checkedIds);} catch (Exception e) {log.error("删除分类异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(CategoryEnum.DELETE_FAIL);}}@Overridepublic CategoryVo findCategoryByCategoryId(Long categoryId)throws ProjectException {try {//按分类id查询分类Category category = categoryService.getById(categoryId);if (!EmptyUtil.isNullOrEmpty(category)){return BeanConv.toBean(category,CategoryVo.class);}return null;} catch (Exception e) {log.error("查找分类所有分类异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(CategoryEnum.SELECT_CATEGORY_FAIL);}}@Overridepublic List<CategoryVo> findCategoryVoList()throws ProjectException {try {//查询分类下拉框return BeanConv.toBeanList(categoryService.findCategoryVoList(),CategoryVo.class);} catch (Exception e) {log.error("查找分类所有分类异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(CategoryEnum.SELECT_CATEGORY_LIST_FAIL);}}}
3.3、ICategoryService业务接口
菜品分类管理的业务接口定义,为CategoryFaceImpl提供核心业务逻辑的定义
package com.itheima.restkeeper.service;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.baomidou.mybatisplus.extension.service.IService;import com.itheima.restkeeper.pojo.Category;import com.itheima.restkeeper.req.CategoryVo;import java.util.List;/*** @Description:菜品及套餐分类 服务类*/public interface ICategoryService extends IService<Category> {/*** @Description 分类列表* @param categoryVo 查询条件* @param pageNum 当前页* @param pageSize 当前页* @return Page<Category>*/Page<Category> findCategoryVoPage(CategoryVo categoryVo, int pageNum, int pageSize);/*** @Description 创建分类* @param categoryVo 对象信息* @return Category*/Category createCategory(CategoryVo categoryVo);/*** @Description 修改分类* @param categoryVo 对象信息* @return Boolean*/Boolean updateCategory(CategoryVo categoryVo);/*** @Description 删除分类* @param checkedIds 选择的分类ID* @return Boolean*/Boolean deleteCategory(String[] checkedIds);/**** @description 查询分类下拉框* @return: List<Category>*/List<Category> findCategoryVoList();/**** @description 查询当前门店的分类* @param storeId* @return List<Category>*/List<Category> findCategoryVoByStoreId(Long storeId);}
3.4、CategoryServiceImpl业务接口实现
菜品分类管理的业务接口定义实现
package com.itheima.restkeeper.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.basic.BasicPojo;import com.itheima.restkeeper.constant.SuperConstant;import com.itheima.restkeeper.pojo.Category;import com.itheima.restkeeper.mapper.CategoryMapper;import com.itheima.restkeeper.req.CategoryVo;import com.itheima.restkeeper.service.ICategoryService;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.itheima.restkeeper.utils.BeanConv;import com.itheima.restkeeper.utils.EmptyUtil;import org.springframework.stereotype.Service;import java.util.ArrayList;import java.util.Arrays;import java.util.List;/*** @Description:菜品分类业务服务实现类*/@Servicepublic class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements ICategoryService {@Overridepublic Page<Category> findCategoryVoPage(CategoryVo categoryVo, int pageNum, int pageSize) {//构建Page<Category>分页对象Page<Category> page = new Page<>(pageNum,pageSize);QueryWrapper<Category> queryWrapper = new QueryWrapper<>();//按分类类型查询if (!EmptyUtil.isNullOrEmpty(categoryVo.getCategoryType())) {queryWrapper.lambda().eq(Category::getCategoryType,categoryVo.getCategoryType());}//按分类名称查询if (!EmptyUtil.isNullOrEmpty(categoryVo.getCategoryName())) {queryWrapper.lambda().likeRight(Category::getCategoryName,categoryVo.getCategoryName());}//按分类有效性查询if (!EmptyUtil.isNullOrEmpty(categoryVo.getEnableFlag())) {queryWrapper.lambda().eq(Category::getEnableFlag,categoryVo.getEnableFlag());}//按sortNo升序排列queryWrapper.lambda().orderByAsc(Category::getSortNo);//执行page查询返回结果return page(page, queryWrapper);}@Overridepublic Category createCategory(CategoryVo categoryVo) {//转换CategoryVo为CategoryCategory category = BeanConv.toBean(categoryVo, Category.class);//执行保存boolean flag = save(category);if (flag){return category;}return null;}@Overridepublic Boolean updateCategory(CategoryVo categoryVo) {//转换CategoryVo为CategoryCategory category = BeanConv.toBean(categoryVo, Category.class);//执行updateById修改return updateById(category);}@Overridepublic Boolean deleteCategory(String[] checkedIds) {//构建选中ids的List<String>List<String> ids = Arrays.asList(checkedIds);List<Long> idsLong = new ArrayList<>();ids.forEach(n->{idsLong.add(Long.valueOf(n));});//执行removeByIds批量移除return removeByIds(idsLong);}@Overridepublic List<Category> findCategoryVoList() {//构建查询条件:SuperConstant.YESQueryWrapper<Category> queryWrapper = new QueryWrapper<>();queryWrapper.lambda().eq(BasicPojo::getEnableFlag, SuperConstant.YES);//执行list查询return list(queryWrapper);}@Overridepublic List<Category> findCategoryVoByStoreId(Long storeId) {//构建查询条件:SuperConstant.YESQueryWrapper<Category> queryWrapper = new QueryWrapper<>();queryWrapper.lambda().eq(Category::getStoreId,storeId).eq(BasicPojo::getEnableFlag, SuperConstant.YES);//执行list查询return list(queryWrapper);}}
3.5、CategoryController类
对TableFace接口进行dubbo的RPC调用,为dubbo服务的消费者
package com.itheima.restkeeper.web;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.CategoryFace;import com.itheima.restkeeper.basic.ResponseWrap;import com.itheima.restkeeper.enums.CategoryEnum;import com.itheima.restkeeper.exception.ProjectException;import com.itheima.restkeeper.req.CategoryVo;import com.itheima.restkeeper.utils.ResponseWrapBuild;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiImplicitParams;import io.swagger.annotations.ApiOperation;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.config.annotation.DubboReference;import org.springframework.web.bind.annotation.*;import java.util.List;/*** @ClassName CategoryController.java* @Description 分类Controller*/@RestController@RequestMapping("category")@Slf4j@Api(tags = "分类controller")public class CategoryController {@DubboReference(version = "${dubbo.application.version}",check = false)CategoryFace categoryFace;/*** @Description 分类列表* @param categoryVo 查询条件* @return*/@PostMapping("page/{pageNum}/{pageSize}")@ApiOperation(value = "查询分类分页",notes = "查询分类分页")@ApiImplicitParams({@ApiImplicitParam(name = "categoryVo",value = "分类查询对象",required = false,dataType = "CategoryVo"),@ApiImplicitParam(paramType = "path",name = "pageNum",value = "页码",dataType = "Integer"),@ApiImplicitParam(paramType = "path",name = "pageSize",value = "每页条数",dataType = "Integer")})public ResponseWrap<Page<CategoryVo>> findCategoryVoPage(@RequestBody CategoryVo categoryVo,@PathVariable("pageNum") int pageNum,@PathVariable("pageSize") int pageSize) {Page<CategoryVo> categoryVoPage = categoryFace.findCategoryVoPage(categoryVo, pageNum, pageSize);return ResponseWrapBuild.build(CategoryEnum.SUCCEED,categoryVoPage);}/*** @Description 添加分类* @param categoryVo 对象信息* @return*/@PostMapping@ApiOperation(value = "添加分类",notes = "添加分类")@ApiImplicitParam(name = "categoryVo",value = "分类对象",required = true,dataType = "CategoryVo")ResponseWrap<CategoryVo> createCategory(@RequestBody CategoryVo categoryVo) {CategoryVo categoryVoResult = categoryFace.createCategory(categoryVo);return ResponseWrapBuild.build(CategoryEnum.SUCCEED,categoryVoResult);}/*** @Description 修改分类* @param categoryVo 对象信息* @return*/@PatchMapping@ApiOperation(value = "修改分类",notes = "修改分类")@ApiImplicitParam(name = "categoryVo",value = "分类对象",required = true,dataType = "CategoryVo")ResponseWrap<Boolean> updateCategory(@RequestBody CategoryVo categoryVo) {Boolean flag = categoryFace.updateCategory(categoryVo);return ResponseWrapBuild.build(CategoryEnum.SUCCEED,flag);}/*** @Description 删除分类* @param categoryVo 查询对象* @return*/@DeleteMapping@ApiOperation(value = "删除分类",notes = "删除分类")@ApiImplicitParam(name = "categoryVo",value = "分类查询对象",required = true,dataType = "CategoryVo")ResponseWrap<Boolean> deleteCategory(@RequestBody CategoryVo categoryVo ) {//获得所有选择分类IDSString[] checkedIds = categoryVo.getCheckedIds();Boolean flag = categoryFace.deleteCategory(checkedIds);return ResponseWrapBuild.build(CategoryEnum.SUCCEED,flag);}/*** @Description 查找分类* @param categoryId 分类id* @return*/@GetMapping("{categoryId}")@ApiOperation(value = "查找分类",notes = "查找分类")@ApiImplicitParam(paramType = "path",name = "categoryId",value = "分类Id",dataType = "Long")ResponseWrap<CategoryVo> findCategoryByCategoryId(@PathVariable("categoryId") Long categoryId) {CategoryVo categoryVo = categoryFace.findCategoryByCategoryId(categoryId);return ResponseWrapBuild.build(CategoryEnum.SUCCEED,categoryVo);}/*** @Description 查找分类* @return*/@GetMapping("list")@ApiOperation(value = "查找分类列表",notes = "查找分类列表")ResponseWrap<List<CategoryVo>> findCategoryVoList() {List<CategoryVo> list = categoryFace.findCategoryVoList();return ResponseWrapBuild.build(CategoryEnum.SUCCEED,list);}@PostMapping("update-category-enableFlag")@ApiOperation(value = "修改分类状态",notes = "修改分类状态")ResponseWrap<Boolean> updateCategoryEnableFlag(@RequestBody CategoryVo categoryVo) {Boolean flag = categoryFace.updateCategory(categoryVo);return ResponseWrapBuild.build(CategoryEnum.SUCCEED,flag);}}
第四章 商家平台-菜品管理
门店管理进行菜品管理的功能,包括对菜品的添加、修改、删除、禁用、启用、起售、停售、查看详情等功能,注意的菜品的数据归属我们采用多租户功能区实现这里不需要考虑【多租户】后面有专题去简介

1、功能区拆解

红色区域:此处为查询条件功能区,筛选列表信息
| 功能 | 说明 |
|---|---|
| 编码 | 输入菜品编码【简码】,键盘按enter触发搜索列表 |
| 菜品名称 | 输入菜品名称,键盘按enter触发搜索列表 |
| 分类 | 下拉框,显示菜品分类【数字字典】,change触发搜索列表 |
| 状态 | 下拉框,显示【启用、禁用】,change触发搜索列表 |
蓝色区域:菜品维护功能
| 功能 | 说明 |
|---|---|
| 添加 | 新增菜品信息 |
| 修改 | 修改菜品信息 |
| 删除 | 删除菜品信息==【真实删除】==,删除时,会有再次确认提示 |
| 详情 | 右侧弹出菜品详细信息 |
| 禁用、启用 | 禁用启用菜品 |
| 起售、停售 | 起售、停售菜品 |

2、数据库结构
CREATE TABLE `tab_dish` (`id` bigint(18) NOT NULL COMMENT '菜品Id',`dish_name` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '菜品名称',`dish_number` int(9) DEFAULT NULL COMMENT '菜品数量',`category_id` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '菜品分类id',`price` decimal(12,4) NOT NULL COMMENT '菜品价格',`reduce_price` decimal(12,4) NOT NULL COMMENT '菜品优惠价格',`code` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '商品码',`description` varchar(400) COLLATE utf8_bin DEFAULT NULL COMMENT '描述信息',`dish_status` varchar(11) COLLATE utf8_bin NOT NULL COMMENT 'YES 停售 NO 起售',`created_time` datetime DEFAULT NULL COMMENT '创建时间',`updated_time` datetime DEFAULT NULL COMMENT '创建时间',`sharding_id` bigint(18) DEFAULT NULL COMMENT '分库id',`store_id` bigint(18) NOT NULL COMMENT '门店主键id',`enterprise_id` bigint(18) NOT NULL COMMENT '商户号',`sort_no` int(11) DEFAULT NULL COMMENT '排序',`enable_flag` varchar(10) CHARACTER SET utf8 NOT NULL COMMENT '是否有效',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='菜品管理';
CREATE TABLE `tab_dish_flavor` (`id` bigint(18) NOT NULL COMMENT '主键Id',`dish_id` bigint(18) DEFAULT NULL COMMENT '菜品id',`data_key` varchar(255) CHARACTER SET utf8 NOT NULL COMMENT '数据字典KEY【数字字典统一管理】',`created_time` datetime DEFAULT NULL COMMENT '创建时间',`updated_time` datetime DEFAULT NULL COMMENT '创建时间',`sharding_id` bigint(18) DEFAULT NULL COMMENT '分库id',`enable_flag` varchar(10) CHARACTER SET utf8 NOT NULL COMMENT '是否有效',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4COMMENT='菜品口味';
自动填充:
下列字段,无需手动填充,系统会自动填充下列字段
| 字段 | 注释 | 填充方式 |
|---|---|---|
| id | 主键 | 雪花算法 |
| enterprise_id | 商户号 | mybatis-plus-多租户拦截 |
| created_time | 创建时间 | mybatis-plus-自动填充组件 |
| updated_time | 修改时间 | mybatis-plus-自动填充组件 |
| sharding_id | 分库id | mybatis-plus-自动填充组件 |
| store_id | 门店id | mybatis-plus-多租户拦截 |
3、功能开发

DishController:对DishFace接口进行dubbo的RPC调用,为dubbo服务的消费者
DishFace:菜品管理dubbo接口定义,对AffixFace图片接口调用
DishFaceImpl:菜品管理dubbo接口定义实现,这里做VO和POJO的转换
IDishService:菜品管理的业务接口定义,为DishFaceImpl提供核心业务逻辑的定义
DishServiceImpl:菜品管理的业务接口定义实现
3.1、DishFace接口
菜品管理dubbo接口定义
package com.itheima.restkeeper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.exception.ProjectException;import com.itheima.restkeeper.req.DishVo;/*** @ClassName DishFace.java* @Description 菜品接口*/public interface DishFace {/*** @Description 菜品列表* @param dishVo 查询条件* @param pageNum 当前页* @param pageSize 每页条数* @return Page<DishVo>*/Page<DishVo> findDishVoPage(DishVo dishVo,int pageNum,int pageSize)throws ProjectException;/*** @Description 创建菜品* @param dishVo 对象信息* @return DishVo*/DishVo createDish(DishVo dishVo)throws ProjectException;/*** @Description 修改菜品* @param dishVo 对象信息* @return Boolean*/Boolean updateDish(DishVo dishVo) throws ProjectException;/*** @Description 删除菜品* @param checkedIds 选择对象信息Id* @return Boolean*/Boolean deleteDish(String[] checkedIds)throws ProjectException;/*** @Description 查找菜品* @param dishId 选择对象信息Id* @return DishVo*/DishVo findDishByDishId(Long dishId)throws ProjectException;}
3.2、DishFaceImpl接口实现
菜品管理dubbo接口定义实现,这里做VO和POJO的转换
package com.itheima.restkeeper.face;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.AffixFace;import com.itheima.restkeeper.DishFace;import com.itheima.restkeeper.constant.AppletCacheConstant;import com.itheima.restkeeper.enums.DishEnum;import com.itheima.restkeeper.exception.ProjectException;import com.itheima.restkeeper.pojo.Dish;import com.itheima.restkeeper.pojo.DishFlavor;import com.itheima.restkeeper.req.AffixVo;import com.itheima.restkeeper.req.DishVo;import com.itheima.restkeeper.service.IDishFlavorService;import com.itheima.restkeeper.service.IDishService;import com.itheima.restkeeper.utils.BeanConv;import com.itheima.restkeeper.utils.EmptyUtil;import com.itheima.restkeeper.utils.ExceptionsUtil;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.config.annotation.DubboReference;import org.apache.dubbo.config.annotation.DubboService;import org.apache.dubbo.config.annotation.Method;import org.redisson.api.RAtomicLong;import org.redisson.api.RLock;import org.redisson.api.RedissonClient;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.transaction.annotation.Transactional;import java.util.ArrayList;import java.util.List;import java.util.concurrent.TimeUnit;import java.util.stream.Collectors;/*** @ClassName DishFaceImpl.java* @Description 菜品接口实现*/@Slf4j@DubboService(version = "${dubbo.application.version}",timeout = 5000,methods ={@Method(name = "findDishVoPage",retries = 2),@Method(name = "createDish",retries = 0),@Method(name = "updateDish",retries = 0),@Method(name = "deleteDish",retries = 0)})public class DishFaceImpl implements DishFace {@AutowiredIDishService dishService;@AutowiredIDishFlavorService dishFlavorService;@AutowiredRedissonClient redissonClient;@DubboReference(version = "${dubbo.application.version}",check = false)AffixFace affixFace;@Overridepublic Page<DishVo> findDishVoPage(DishVo dishVo,int pageNum,int pageSize)throws ProjectException {try {//查询菜品分页Page<Dish> page = dishService.findDishVoPage(dishVo, pageNum, pageSize);Page<DishVo> pageVo = new Page<>();BeanConv.toBean(page,pageVo);//结果集转换List<Dish> dishList = page.getRecords();List<DishVo> dishVoList = BeanConv.toBeanList(dishList,DishVo.class);if (!EmptyUtil.isNullOrEmpty(dishVoList)){dishVoList.forEach(n->{//处理附件List<AffixVo> affixVoList = affixFace.findAffixVoByBusinessId(n.getId());if (!EmptyUtil.isNullOrEmpty(affixVoList)){n.setAffixVo(affixVoList.get(0));}//处理口味1List<DishFlavor> dishFlavors = dishFlavorService.findDishFlavorByDishId(n.getId());List<String> dishFavorList = new ArrayList<>();for (DishFlavor dishFlavor : dishFlavors) {dishFavorList.add(String.valueOf(dishFlavor.getDataKey()));}String[] dishFlavorDataKey = new String[dishFavorList.size()];dishFavorList.toArray(dishFlavorDataKey);n.setHasDishFlavor(dishFlavorDataKey);});}pageVo.setRecords(dishVoList);//返回结果return pageVo;} catch (Exception e) {log.error("查询菜品列表异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(DishEnum.PAGE_FAIL);}}@Override@Transactionalpublic DishVo createDish(DishVo dishVo) throws ProjectException{try {//创建菜品DishVo dishVoResult = BeanConv.toBean(dishService.createDish(dishVo), DishVo.class);dishVoResult.setHasDishFlavor(dishVo.getHasDishFlavor());//绑定附件if (!EmptyUtil.isNullOrEmpty(dishVoResult)){affixFace.bindBusinessId(AffixVo.builder().businessId(dishVoResult.getId()).id(dishVo.getAffixVo().getId()).build());}dishVoResult.setAffixVo(AffixVo.builder().pathUrl(dishVo.getAffixVo().getPathUrl()).businessId(dishVoResult.getId()).id(dishVo.getAffixVo().getId()).build());//构建初始化库存String key = AppletCacheConstant.REPERTORY_DISH+dishVoResult.getId();RAtomicLong atomicLong = redissonClient.getAtomicLong(key);atomicLong.set(dishVoResult.getDishNumber());return dishVoResult;} catch (Exception e) {log.error("保存菜品异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(DishEnum.CREATE_FAIL);}}@Override@Transactionalpublic Boolean updateDish(DishVo dishVo) throws ProjectException {Boolean flag = false;//修改菜品flag = dishService.updateDish(dishVo);//处理菜品图片if (flag){List<AffixVo> affixVoList = affixFace.findAffixVoByBusinessId(dishVo.getId());List<Long> affixIds = affixVoList.stream().map(AffixVo::getId).collect(Collectors.toList());if (!affixIds.contains(dishVo.getAffixVo().getId())){//删除图片flag = affixFace.deleteAffixVoByBusinessId(dishVo.getId());//绑定新图片affixFace.bindBusinessId(AffixVo.builder().businessId(dishVo.getId()).id(dishVo.getAffixVo().getId()).build());}}//构建redis库存String key = AppletCacheConstant.REPERTORY_DISH+dishVo.getId();RAtomicLong atomicLong = redissonClient.getAtomicLong(key);atomicLong.set(dishVo.getDishNumber());return flag;}@Override@Transactionalpublic Boolean deleteDish(String[] checkedIds)throws ProjectException {try {Boolean flag = dishService.deleteDish(checkedIds);for (String checkedId : checkedIds) {//删除图片affixFace.deleteAffixVoByBusinessId(Long.valueOf(checkedId));//删除菜品库存String key = AppletCacheConstant.REPERTORY_DISH+checkedId;RAtomicLong atomicLong = redissonClient.getAtomicLong(key);atomicLong.delete();}return flag;} catch (Exception e) {log.error("删除菜品异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(DishEnum.DELETE_FAIL);}}@Overridepublic DishVo findDishByDishId(Long dishId)throws ProjectException {try {//按菜品ID查找菜品Dish dish = dishService.getById(dishId);if (!EmptyUtil.isNullOrEmpty(dish)){return BeanConv.toBean(dish,DishVo.class);}return null;} catch (Exception e) {log.error("查找菜品所有菜品异常:{}", ExceptionsUtil.getStackTraceAsString(e));throw new ProjectException(DishEnum.SELECT_DISH_FAIL);}}}
3.3、IDishService业务接口
菜品管理的业务接口定义,为DishFaceImpl提供核心业务逻辑的定义
package com.itheima.restkeeper.service;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.pojo.Dish;import com.itheima.restkeeper.pojo.Dish;import com.baomidou.mybatisplus.extension.service.IService;import com.itheima.restkeeper.req.DishVo;import java.util.List;/*** @Description:菜品管理 服务类*/public interface IDishService extends IService<Dish> {/*** @Description 菜品列表* @param dishVo 查询条件* @param pageNum 当前页* @param pageSize 每页条数* @return Page<Dish>*/Page<Dish> findDishVoPage(DishVo dishVo, int pageNum, int pageSize);/*** @Description 创建菜品* @param dishVo 对象信息* @return Dish*/Dish createDish(DishVo dishVo);/*** @Description 修改菜品* @param dishVo 对象信息* @return Boolean*/Boolean updateDish(DishVo dishVo);/*** @Description 删除菜品* @param checkedIds 选择的菜品ID* @return Boolean*/Boolean deleteDish(String[] checkedIds);/**** @description 查询分类下所有菜品* @param categoryId* @return List<Dish>*/List<Dish> findDishVoByCategoryId(Long categoryId);/**** @description 查询店铺下所有起售且有效菜品* @param storeId* @return List<Dish>*/List<Dish> findDishVoByStoreId(Long storeId);/**** @description 增减菜品库存数量* @param step 增减步长* @return Boolean*/Boolean updateDishNumber(Long step, Long dishId);/**** @description 查询所有有效的菜品信息* @return*/List<Dish> findDishVos();}
3.4、DishServiceImpl业务接口实现
菜品管理的业务接口定义实现
package com.itheima.restkeeper.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.google.common.collect.Lists;import com.itheima.restkeeper.constant.SuperConstant;import com.itheima.restkeeper.pojo.Dish;import com.itheima.restkeeper.mapper.DishMapper;import com.itheima.restkeeper.pojo.DishFlavor;import com.itheima.restkeeper.req.DishVo;import com.itheima.restkeeper.service.IDishFlavorService;import com.itheima.restkeeper.service.IDishService;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.itheima.restkeeper.utils.BeanConv;import com.itheima.restkeeper.utils.EmptyUtil;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import java.util.ArrayList;import java.util.Arrays;import java.util.List;/*** @Description:菜品管理 服务实现类*/@Servicepublic class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements IDishService {@AutowiredIDishFlavorService dishFlavorService;@AutowiredDishMapper dishMapper;@Overridepublic Page<Dish> findDishVoPage(DishVo dishVo, int pageNum, int pageSize) {//构建Page<Dish>分页对象Page<Dish> page = new Page<>(pageNum,pageSize);QueryWrapper<Dish> queryWrapper = new QueryWrapper<>();//按分类查询if (!EmptyUtil.isNullOrEmpty(dishVo.getCategoryId())) {queryWrapper.lambda().eq(Dish::getCategoryId,dishVo.getCategoryId());}//按菜品名称查询if (!EmptyUtil.isNullOrEmpty(dishVo.getDishName())) {queryWrapper.lambda().likeRight(Dish::getDishName,dishVo.getDishName());}//按简码查询if (!EmptyUtil.isNullOrEmpty(dishVo.getCode())) {queryWrapper.lambda().likeRight(Dish::getCode,dishVo.getCode());}//按有效性查询if (!EmptyUtil.isNullOrEmpty(dishVo.getEnableFlag())) {queryWrapper.lambda().eq(Dish::getEnableFlag,dishVo.getEnableFlag());}//按sortNo升序queryWrapper.lambda().orderByAsc(Dish::getSortNo);//执行page返回结果return page(page, queryWrapper);}@Override@Transactionalpublic Dish createDish(DishVo dishVo) {//转换DishVo为DishDish dish = BeanConv.toBean(dishVo, Dish.class);//执行保存boolean flag = save(dish);//保存菜品和口味中间表信息if (flag){List<DishFlavor> list = Lists.newArrayList();List<String> dataKeys = Arrays.asList(dishVo.getHasDishFlavor());dataKeys.forEach(n->{DishFlavor dishFlavor = DishFlavor.builder().dishId(dish.getId()).dataKey(n).build();list.add(dishFlavor);});flag = dishFlavorService.saveBatch(list);}if (flag){return dish;}return null;}/*** @Description 菜品拥有的口味*/private List<String> dishHasDishFlavor(Long dishId){QueryWrapper<DishFlavor> queryWrapper = new QueryWrapper<>();queryWrapper.lambda().eq(DishFlavor::getDishId,dishId);List<DishFlavor> list = dishFlavorService.list(queryWrapper);ArrayList<String> listDataKeys = Lists.newArrayList();if (!EmptyUtil.isNullOrEmpty(list)){list.forEach(n->{listDataKeys.add(String.valueOf(n.getDataKey()));});}return listDataKeys;}@Overridepublic Boolean updateDish(DishVo dishVo) {Dish dish = BeanConv.toBean(dishVo, Dish.class);boolean flag = updateById(dish);if (flag){//删除以往有的口味QueryWrapper<DishFlavor> queryWrapper = new QueryWrapper<>();queryWrapper.lambda().eq(DishFlavor::getDishId,dish.getId());dishFlavorService.remove(queryWrapper);}//添加新口味List<DishFlavor> list = Lists.newArrayList();List<String> newDishHasDishFlavors = Arrays.asList(dishVo.getHasDishFlavor());newDishHasDishFlavors.forEach(n->{DishFlavor dishFlavors = DishFlavor.builder().dishId(dish.getId()).dataKey(n).build();list.add(dishFlavors);});flag = dishFlavorService.saveBatch(list);return flag;}@Overridepublic Boolean deleteDish(String[] checkedIds) {//构建选择ids的List<String>List<String> ids = Arrays.asList(checkedIds);List<Long> idsLong = new ArrayList<>();ids.forEach(n->{idsLong.add(Long.valueOf(n));});//批量移除菜品boolean flag = removeByIds(idsLong);//批量移除菜品口味if (flag){QueryWrapper<DishFlavor> queryWrapper = new QueryWrapper<>();queryWrapper.lambda().in(DishFlavor::getDishId,idsLong);flag = dishFlavorService.remove(queryWrapper);}return flag;}@Overridepublic List<Dish> findDishVoByCategoryId(Long categoryId) {//构建查询条件:菜品起售,菜品有效LambdaQueryWrapper<Dish> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(Dish::getCategoryId,categoryId).eq(Dish::getEnableFlag,SuperConstant.YES).eq(Dish::getDishStatus,SuperConstant.YES);//执行list查询return list(lambdaQueryWrapper);}@Overridepublic List<Dish> findDishVoByStoreId(Long storeId) {//构建查询条件:店铺ID,菜品起售,菜品有效LambdaQueryWrapper<Dish> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(Dish::getStoreId,storeId).eq(Dish::getEnableFlag,SuperConstant.YES).eq(Dish::getDishStatus,SuperConstant.YES);//执行list查询return list(lambdaQueryWrapper);}@Overridepublic Boolean updateDishNumber(Long step,Long dishId) {//修改菜品数量Integer row = dishMapper.updateDishNumber(step,dishId);return row==1 ? true:false;}@Overridepublic List<Dish> findDishVos() {QueryWrapper<Dish> queryWrapper = new QueryWrapper<>();queryWrapper.lambda().eq(Dish::getEnableFlag,SuperConstant.YES).eq(Dish::getDishStatus,SuperConstant.YES);return list(queryWrapper);}}
3.5、DishController类
对DishFace接口进行dubbo的RPC调用,为dubbo服务的消费者
package com.itheima.restkeeper.web;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.itheima.restkeeper.DishFace;import com.itheima.restkeeper.basic.ResponseWrap;import com.itheima.restkeeper.enums.DishEnum;import com.itheima.restkeeper.req.DishVo;import com.itheima.restkeeper.utils.ResponseWrapBuild;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiImplicitParams;import io.swagger.annotations.ApiOperation;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.config.annotation.DubboReference;import org.springframework.web.bind.annotation.*;/*** @ClassName DishController.java* @Description 菜品Controller*/@RestController@RequestMapping("dish")@Slf4j@Api(tags = "菜品controller")public class DishController {@DubboReference(version = "${dubbo.application.version}",check = false)DishFace dishFace;/*** @Description 菜品列表* @param dishVo 查询条件* @return*/@PostMapping("page/{pageNum}/{pageSize}")@ApiOperation(value = "查询菜品分页",notes = "查询菜品分页")@ApiImplicitParams({@ApiImplicitParam(name = "dishVo",value = "菜品查询对象",dataType = "DishVo"),@ApiImplicitParam(paramType = "path",name = "pageNum",value = "页码",dataType = "Integer"),@ApiImplicitParam(paramType = "path",name = "pageSize",value = "每页条数",dataType = "Integer")})public ResponseWrap<Page<DishVo>> findDishVoPage(@RequestBody DishVo dishVo,@PathVariable("pageNum") int pageNum,@PathVariable("pageSize") int pageSize) {Page<DishVo> dishVoPage = dishFace.findDishVoPage(dishVo, pageNum, pageSize);return ResponseWrapBuild.build(DishEnum.SUCCEED,dishVoPage);}/*** @Description 添加菜品* @param dishVo 对象信息* @return*/@PostMapping@ApiOperation(value = "添加菜品",notes = "添加菜品")@ApiImplicitParam(name = "dishVo",value = "菜品对象",required = true,dataType = "DishVo")ResponseWrap<DishVo> createDish(@RequestBody DishVo dishVo) {DishVo dishVoResult = dishFace.createDish(dishVo);return ResponseWrapBuild.build(DishEnum.SUCCEED,dishVoResult);}/*** @Description 修改菜品* @param dishVo 对象信息* @return*/@PatchMapping@ApiOperation(value = "修改菜品",notes = "修改菜品")@ApiImplicitParam(name = "dishVo",value = "菜品对象",required = true,dataType = "DishVo")ResponseWrap<Boolean> updateDish(@RequestBody DishVo dishVo) {Boolean flag = dishFace.updateDish(dishVo);return ResponseWrapBuild.build(DishEnum.SUCCEED,flag);}/*** @Description 删除菜品* @param dishVo 查询对象* @return*/@DeleteMapping@ApiOperation(value = "删除菜品",notes = "删除菜品")@ApiImplicitParam(name = "dishVo",value = "菜品查询对象",required = true,dataType = "DishVo")ResponseWrap<Boolean> deleteDish(@RequestBody DishVo dishVo ) {//获得所有选中的菜品IDSString[] checkedIds = dishVo.getCheckedIds();Boolean flag = dishFace.deleteDish(checkedIds);return ResponseWrapBuild.build(DishEnum.SUCCEED,flag);}/*** @Description 查找菜品* @param dishId 菜品id* @return*/@GetMapping("{dishId}")@ApiOperation(value = "查找菜品",notes = "查找菜品")@ApiImplicitParam(paramType = "path",name = "dishId",value = "菜品Id",dataType = "Long")ResponseWrap<DishVo> findDishByDishId(@PathVariable("dishId") Long dishId) {DishVo dishVo = dishFace.findDishByDishId(dishId);return ResponseWrapBuild.build(DishEnum.SUCCEED,dishVo);}@PostMapping("update-dish-enableFlag")@ApiOperation(value = "修改菜品有效状态",notes = "修改菜品有效状态")ResponseWrap<Boolean> updateDishEnableFlag(@RequestBody DishVo dishVo) {Boolean flag = dishFace.updateDish(dishVo);return ResponseWrapBuild.build(DishEnum.SUCCEED,flag);}@PostMapping("update-dish-dishStatus")@ApiOperation(value = "修改菜品状态",notes = "修改菜品状态")ResponseWrap<Boolean> updateDishDishStatus(@RequestBody DishVo dishVo) {Boolean flag = dishFace.updateDish(dishVo);return ResponseWrapBuild.build(DishEnum.SUCCEED,flag);}}
课堂讨论
1、概述区域、桌台、分类、菜品表之间的关系,及关键字段。
2、项目中区域、桌台、分类、菜品是否有企业归属及门店归属的概念?在设计数据库的时候需要注意什么?
3、菜品的库存的控制你是这么理解的?菜品库存与那些操作有关?
4、设计一下==《汽车维修4S美容中心》==中的表结构
课后任务
1、完成区域、桌台、分类、菜品管理开发,同步到git【☆☆☆☆☆】
2、完成当天课堂讨论,同步到git【☆☆☆☆☆】
3、完成2-5道sql练习【☆☆☆☆】
4、梳理项目一业务,同步到git【☆☆☆】
