分类信息我们要用一个新的表来存储——category

我们添加的菜品/套餐名称,是唯一的,不能够重复的,所以在设计表结构时,已经针对于name字段建立了唯一索引 。
dish(菜品表)

setmeal(套餐表)

后台系统中可以管理分类信息,分类包括两种类型,分别是 菜品分类 和 套餐分类 。当我们在后台系统中添加菜品时需要选择一个菜品分类,当我们在后台系统中添加一个套餐时需要选择一个套餐分类,在移动端也会按照菜品分类和套餐分类来展示对应的菜品和套餐。

在分类管理中,我们新增分类时,可以选择新增菜品分类(川菜、湘菜、粤菜...),也可以选择新增套餐分类(营养早餐、超值午餐...)。
在添加套餐的时候,输入的排序字段,控制的是移动端套餐列表的展示顺序。


这个点说白了就是实现一个分页查询功能。
在分类管理列表页面,可以对某个分类进行删除操作。需要注意的是当分类关联了菜品或者套餐时,此分类不允许删除。

根据当前分类的ID,查询该分类下是否存在菜品,如果存在,则提示错误信息
根据当前分类的ID,查询该分类下是否存在套餐,如果存在,则提示错误信息
在分类管理列表页面点击修改按钮,弹出修改窗口,在修改窗口回显分类信息并进行修改,最后点击确定按钮完成修改操作。

注:这里的回显是前端帮我们做的!

在开发代码之前,需要梳理一下整个程序的执行过程
(1)在页面(backend/page/category/list.html)的新增分类表单中填写数据,点击 "确定" 发送ajax请求,将新增分类窗口输入的数据以json形式提交到服务端
(2)服务端Controller接收页面提交的数据并调用Service将数据进行保存
(3)Service调用Mapper操作数据库,保存数据
可以看到新增菜品分类和新增套餐分类请求的服务端地址和提交的json数据结构相同,所以服务端只需要提供一个方法统一处理

- v-if="action != 'edit'"
- type="primary"
- size="medium"
- class="continue"
- @click="submitForm('go')"
- > 保存并继续添加

- // 新增接口
- const addCategory = (params) => {
- return $axios({
- url: '/category',
- method: 'post',
- data: { ...params }
- })
- }
所以说当我们在前端页面点击 “保存并继续添加” 时,就会发送POST的请求,具体如下:
请求 说明 请求方式 POST 请求路径 /category 请求参数 json格式 - {"name":"川菜","type":"1","sort":2}
2. 分类信息分页查询
在开发代码之前,需要梳理一下整个程序的执行过程
(1)页面发送ajax请求,将分页查询参数(page、pageSize)提交到服务端
(2)服务端Controller接收页面提交的数据并调用Service查询数据
(3)Service调用Mapper操作数据库,查询分页数据
(4)Controller将查询到的分页数据响应给页面
(5)页面接收到分页数据并通过ElementUI的Table组件展示到页面上

- // 查询列表接口
- const getCategoryPage = (params) => {
- return $axios({
- url: '/category/page',
- method: 'get',
- params
- })
- }
具体的请求信息整理如下
请求 说明 请求方式 GET 请求路径 /category/page 请求参数 ?page=1&pageSize=10
3. 删除分类
在开发代码之前,需要梳理一下整个程序的执行过程
(1)点击删除,页面发送ajax请求,将参数(id)提交到服务端
(2)服务端Controller接收页面提交的数据并调用Service删除数据
(3)Service调用Mapper操作数据库

- // 删除当前列的接口
- const deleCategory = (id) => {
- return $axios({
- url: '/category',
- method: 'delete',
- params: { id }
- })
- }
请求 说明 请求方式 DELETE 请求路径 /category 请求参数 ?id=1395291114922618881
4. 修改分类

请求 说明 请求方式 PUT 请求路径 /category 请求参数 {id: "1399923597874081794", name: "超值午餐", sort: 0}
代码实现
CategoryMapper
- @Mapper
- public interface CategoryMapper extends BaseMapper
{ - }
CategoryService
- public interface CategoryService extends IService
{ -
- R
saveSortInfo(Category category); -
- R
deleteSortInfo(Long id); -
- R
pageSortInfo(int page, int pageSize); -
- R
updateSortInfo(Category category); - }
CategoryServiceImpl
- @Service
- public class CategoryServiceImpl extends ServiceImpl
implements CategoryService { -
- @Autowired
- private CategoryMapper categoryMapper;
-
- @Autowired
- private DishMapper dishMapper;
-
- @Autowired
- private SetmealMapper setmealMapper;
-
- @Override
- public R
saveSortInfo(Category category) { - categoryMapper.insert(category);
- return R.success("新增分类成功!");
- }
-
- @Override
- public R
deleteSortInfo(Long id) { - // 添加查询条件,根据分类id进行查询菜品数据
- LambdaQueryWrapper
dishLambdaQueryWrapper = new LambdaQueryWrapper<>(); - dishLambdaQueryWrapper.eq(Dish::getCategoryId, id);
- int count1 = dishMapper.selectCount(dishLambdaQueryWrapper);
-
- // 如果已经关联,抛出一个业务异常
- if (count1 > 0) {
- throw new CustomException("当前分类下关联了菜品,不能删除!");
- }
-
- // 查询当前分类是否关联了套餐,如果已经关联,抛出一个业务异常
- LambdaQueryWrapper
setmealLambdaQueryWrapper = new LambdaQueryWrapper<>(); - setmealLambdaQueryWrapper.eq(Setmeal::getCategoryId, id);
- int count2 = setmealMapper.selectCount(setmealLambdaQueryWrapper);
-
- if (count2 > 0) {
- throw new CustomException("当前分类下套餐了菜品,不能删除!");
- }
-
- super.removeById(id);
- return R.success("分类信息删除成功!");
- }
-
- @Override
- public R
updateSortInfo(Category category) { - categoryMapper.updateById(category);
- return R.success("修改完成!");
- }
-
- @Override
- public R
pageSortInfo(int page, int pageSize) { - Page
pageInfo = new Page<>(page, pageSize); - LambdaQueryWrapper
queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.orderByAsc(Category::getSort);
- categoryMapper.selectPage(pageInfo, queryWrapper);
- return R.success(pageInfo);
- }
- }
CategoryController
- /**
- * 分类管理
- */
- @Slf4j
- @RestController
- @RequestMapping("/category")
- public class CategoryController {
-
- @Autowired
- private CategoryService categoryService;
-
- /**
- * 新增菜品
- * @param category
- * @return
- */
- @PostMapping
- public R
saveSortInfo(@RequestBody Category category) { - return categoryService.saveSortInfo(category);
- }
-
- /**
- * 删除菜品,根据id删除分类,删除之前做一下判断,是否有关联
- * @param id
- * @return
- */
- @DeleteMapping
- public R
deleteSortInfo(Long id) { - return categoryService.deleteSortInfo(id);
- }
-
- /**
- * 修改菜品
- * @param category
- * @return
- */
- @PutMapping
- public R
updateSortInfo(@RequestBody Category category) { - return categoryService.updateSortInfo(category);
- }
-
- /**
- * 分页
- * @param page
- * @param pageSize
- * @return
- */
- @GetMapping("/page")
- public R
pageSortInfo(int page, int pageSize) { - return categoryService.pageSortInfo(page, pageSize);
- }
-
- }
创建自定义异常
- /**
- * 自定义业务异常类
- */
- public class CustomException extends RuntimeException{
- public CustomException(String msg) {
- super(msg);
- }
- }
GlobalExceptionHandler
- /**
- * 全局异常处理
- * @ControllerAdvice: 表示拦截 类上有 @RestController 注解的类
- * @ResponseBody:封装成JSON数据
- */
- @ControllerAdvice(annotations = {RestController.class, Controller.class})
- @ResponseBody
- @Slf4j
- public class GlobalExceptionHandler {
-
- /**
- * 异常处理方法
- * @return
- */
- @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
- public R
exceptionHandler(SQLIntegrityConstraintViolationException ex){ - log.error(ex.getMessage());
- if(ex.getMessage().contains("Duplicate entry")){
- String[] split = ex.getMessage().split(" ");
- String msg = split[2] + "已存在";
- return R.error(msg);
- }
- return R.error("未知错误");
- }
-
- /**
- * 异常处理方法
- * @return
- */
- @ExceptionHandler(CustomException.class)
- public R
exceptionHandler(CustomException ex){ - log.error(ex.getMessage());
-
- return R.error(ex.getMessage());
- }
- }
代码获取(免费)