03-瑞吉外卖关于菜品/套餐分类表的增删改查

新增菜品/套餐分类

页面原型

当我们在后台系统中添加菜品/套餐时,需要选择一个菜品/套餐分类,在移动端也会按照菜品分类和套餐分类来展示对应的菜品和套餐

第一步: 用户点击确定按钮执行submitForm函数发送Ajax请求,将新增菜品/套餐表单中输入的数据以json形式提交给服务端,等待服务端响应数据后执行回调函数

在这里插入图片描述

<!--用户在表单页面category/list.html中填写分类名称和排序数字-->
<el-form class="demo-form-inline" label-width="100px"><el-form-item label="分类名称:"><el-input v-model="classData.name" placeholder="请输入分类名称" maxlength="14"/></el-form-item><el-form-item label="排序:"><el-input v-model="classData.sort"  type="number" placeholder="请输入排序" /></el-form-item>
</el-form><span slot="footer" class="dialog-footer"><el-button size="medium" @click="classData.dialogVisible = false">取 消</el-button><el-button type="primary" size="medium" @click="submitForm()">确 定</el-button><el-button v-if="action != 'edit'" type="primary" size="medium" class="continue" @click="submitForm('go')"> 保存并继续添加 </el-button>
submitForm(st) {const classData = this.classDataconst valid = (classData.name === 0 ||classData.name)  && (classData.sort === 0 || classData.sort)if (this.action === 'add') {if (valid) {const reg = /^\d+$/if (reg.test(classData.sort)) {addCategory({'name': classData.name,'type':this.type, sort: classData.sort}).then(res => {console.log(res)if (res.code === 1) {this.$message.success('分类添加成功!')if (!st) {this.classData.dialogVisible = false} else {this.classData.name = ''this.classData.sort = ''}this.handleQuery()}}}}}

第二步: 服务端Controller接收页面提交的数据并通过Service调用Mapper操作数据库保存添加的菜品/套餐分类信息

在这里插入图片描述

数据模型

数据模型category表: id是主键,name字段表示分类名称是唯一的,type字段为1表示菜品分类,为2表示套餐分类

在这里插入图片描述

后端处理请求

第一步: 创建实体类Category,对于createUser和createTime等公共字段使用自动填充功能

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

第二步: 创建Mapper接口CategoryMapper和Service接口CategoryService及其实现类CatrgoryServiceImpl

@Mapper
public interface CategoryMapper extends BaseMapper<Category> {
}public interface CategoryService extends IService<Category> {
}@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
}

第三步: 在CategoryController控制层中编写控制器方法,将接收到的json数据添加到数据库中并响应一个成功的提示信息

@Slf4j
@RestController
@RequestMapping("/category")
public class CategoryController {@Autowiredprivate CategoryService categoryService;@PostMappingpublic Result<String> save(@RequestBody Category category) {log.info("category:{}", category);categoryService.save(category);return Result.success("新增分类成功");}
}

分页查询所有菜品/套餐分类

页面原型

第一步:用户点击分页管理按钮时携带分页查询的相关参数page(默认1)、pageSize(默认10)发送Ajax请求到服务端去查询菜品/套餐的分类信息

在这里插入图片描述

第二步: 服务端Controller接受到请求之后通过Service调用Mapper操作数据库查询相关的菜品/套餐信息

在这里插入图片描述

第三步: Controller将查询到的所有数据和分页信息响应给前端

第四步: 前端接收到后端响应的数据后,通过ElementUI的Table组件渲染到页面上

  • 页面加载完毕之后调用created钩子函数,在该钩子函数内又调用init函数进行初始化
created() {this.init()
}
async init () {await getCategoryPage({'page': this.page, 'pageSize': this.pageSize}).then(res => {if (String(res.code) === '1') {//将服务端查询到的所有数据赋给tableData,然后就能看到了this.tableData = res.data.recordsthis.counts = Number(res.data.total)} else {this.$message.error(res.msg || '操作失败')}}).catch(err => {this.$message.error('请求出错了:' + err)})
}
// 查询列表接口
const getCategoryPage = (params) => {return $axios({url: '/category/page',method: 'get',params})
}

后端处理请求

执行categoryService提供的page方法进行分页查询并将查询到的数据和分页信息响应给前端

@GetMapping("/page")
public Result<Page> page(int page, int pageSize) {// 创建分页构造器Page<Category> pageInfo = new Page<>(page, pageSize);// 构造条件查询器LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();// 添加排序条件,根据sort属性进行排序queryWrapper.orderByDesc(Category::getSort);// 执行分页查询的语句categoryService.page(pageInfo, queryWrapper);// 将查询到的所有数据和分页相关的信息响应给前端return Result.success(pageInfo);
}

删除某个分类(判断有无关联)

页面原型

第一步:在分类管理列表页面, 用户点击某个分类对应的删除按钮发送Ajax请求,请求参数就是该菜品/套餐分类单元格对应的属性Id

  • 删除是个危险的操作,当用户点击删除按钮时先给一个提示信息防止误操作,当用户点确定后才会执行deleCategory回调函数

在这里插入图片描述

<el-buttontype="text"size="small"class="delBut non"<!--删除按钮绑定了deleteHandle函数,参数就是当前单元格的Id-->@click="deleteHandle(scope.row.id)">
</el-button>
<script>deleteHandle(id) {this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {'confirmButtonText': '确定','cancelButtonText': '取消','type': 'warning'}).then(() => {deleCategory(id).then(res => {// 服务端成功删除后提示'删除成功!'if (res.code === 1) {this.$message.success('删除成功!')this.handleQuery()} else {this.$message.error(res.msg || '操作失败')}}).catch(err => {this.$message.error('请求出错了:' + err)})})}// 发其Ajax请求删除当前行const deleCategory = (id) => {return $axios({url: '/category',method: 'delete',params: {id}})}
</script>

第二步:服务端Controller接收页面提交的菜品/套餐分类的Id,通过Service调用Mapper根据Id删除对应的纪录,如果该分类关联了某个菜品或套餐时不允许被删除

在这里插入图片描述

后端处理请求(无关联)

@DeleteMapping
private Result<String> delete(Long id) {log.info("将被删除的id:{}", id);categoryService.removeById(id);return Result.success("分类信息删除成功");
}

查询菜品/套餐

删除某个分类时需要先拿着当前分类的Id值去对应的菜品/套餐表中进行查询,如果能查询到数据则说明该分类关联了菜品/套餐,此时不能删除该分类

在这里插入图片描述

数据模型

套餐信息表setmeal

在这里插入图片描述

菜品信息表dish

在这里插入图片描述

后端处理请求

第一步: 创建菜品表和套餐表对应的模型类DishStemal,对于createUser和createTimecreateUser和updateUser等公共字段使用自动填充功能

/**菜品*/
@Data
public class Dish implements Serializable {private static final long serialVersionUID = 1L;private Long id;//菜品名称private String name;//菜品分类idprivate 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;
}
/*** 套餐*/
@Data
public class Setmeal implements Serializable {private static final long serialVersionUID = 1L;private Long id;//分类idprivate 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;
}

第二步: 编写对应的Mapper接口和Service接口及其实现类

@Mapper
public interface DishMapper extends BaseMapper<Dish> {
}@Mapper
public interface SetmealMapper extends BaseMapper<Setmeal> {
}public interface SetmealService extends IService<Setmeal> {
}
@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {
}public interface DishService extends IService<Dish> {
}
@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {
}

第三步: 在common包下新增CustomException异常类用于封装我们的自定义异常

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

第四步: 在全局异常处理器中使用@ExceptionHandler注解专门处理CustomerException类型的异常

@ExceptionHandler(CustomException.class)
public Result<String> exceptionHandler(CustomException exception) {log.error(exception.getMessage());return Result.error(exception.getMessage());
}

第五步: CategoryService接口中新增remove方法, 在删除数据之前先根据当前菜品/套餐分类的categoryId值去dish表和setmeal表中查询是否关联了数据

  • 如果查询到了数据: 说明存在关联的菜品/套餐数据即不能删除需要抛出一个自定义异常
  • 如果查询不到数据: 说明不存在关联的菜品/套餐数据那么可以正常删除
@Service
@Slf4j
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {@AutowiredDishService dishService;@AutowiredSetmealService setmealService;/*** 根据id删除分类,删除之前需要进行判断* @param id*/@Overridepublic void remove(Long id) {// 根据菜品的分类id去菜品表中查询关联的菜品记录LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();dishLambdaQueryWrapper.eq(Dish::getCategoryId, id);int count1 = dishService.count(dishLambdaQueryWrapper);// 判断菜品当前分类是否关联了菜品,如果已经关联则抛出异常if (count1 > 0){throw new CustomException("当前分类下关联了菜品,不能删除");}// 根据套餐的分类id去套餐表中查询关联的套餐记录LambdaQueryWrapper<Setmeal> setmealLambdaQueryWrapper = new LambdaQueryWrapper<>();setmealLambdaQueryWrapper.eq(Setmeal::getCategoryId,id);// 判断当前套餐分类是否关联了套餐,如果已经关联则抛出异常int count2 = setmealService.count(setmealLambdaQueryWrapper);if (count2 > 0){throw new CustomException("当前分类下关联了套餐,不能删除");}// 没有关联菜品/套餐则调用CategoryService自带的removeById方法正常删除super.removeById(id);}
}

第六步: 在Controller中调用CategoryService新增的remove方法

@DeleteMapping
public Result<String> delete(Long id){log.info("将要删除的分类id:{}",id);categoryService.remove(id);return Result.success("分类信息删除成功");
}

修改分类信息

页面原型

第一步: 用户在分类管理列表页面中点击修改"按钮后弹出修改窗口,此时会回显当前菜品/套餐分类的信息并等待用户修改(通过Vue的数据绑定功能实现自动回显)

在这里插入图片描述

<el-buttontype="text"size="small"class="blueBug"<!--回显当前分类的信息,参数就是当前单元格的信息-->@click="editHandle(scope.row)"
>
修改
</el-button><el-formclass="demo-form-inline"label-width="100px"><el-form-item label="分类名称:"><el-inputv-model="classData.name"placeholder="请输入分类名称"maxlength="14"/></el-form-item><el-form-item label="排序:"><el-input v-model="classData.sort"  type="number" placeholder="请输入排序" /></el-form-item>
</el-form><script>editHandle(dat) {// 这里并没有从后端查数据进行回显,而是对Vue双向绑定的数据classData下的name和sort属性进行赋值实现回显效果this.classData.title = '修改分类'this.action = 'edit'this.classData.name = dat.namethis.classData.sort = dat.sortthis.classData.id = dat.idthis.classData.dialogVisible = true}classData: {'title': '添加菜品分类','dialogVisible': false,'categoryId': '','name': '',sort: ''}
</script>

第二步: 用户点击确定按钮后执行通用的submitForm函数发起Ajax请求,以json格式提交修改后的菜品/套餐分类信息
在这里插入图片描述

<script>submitForm(st) {const classData = this.classDataconst valid = (classData.name === 0 ||classData.name)  && (classData.sort === 0 || classData.sort)// 添加操作从这里执行if (this.action === 'add') {if (valid) {const reg = /^\d+$/if (reg.test(classData.sort)) {addCategory({'name': classData.name,'type':this.type, sort: classData.sort}).then(res => {console.log(res)if (res.code === 1) {this.$message.success('分类添加成功!')if (!st) {this.classData.dialogVisible = false} else {this.classData.name = ''this.classData.sort = ''}this.handleQuery()} else {this.$message.error(res.msg || '操作失败')}}).catch(err => {this.$message.error('请求出错了:' + err)})} else {this.$message.error('排序只能输入数字类型')}} else {this.$message.error('请输入分类名称或排序')}// 修改操作从这里执行} else if (valid) {const reg = /^\d+$/if (reg.test(this.classData.sort)) {// 发起ajax请求修改员工数据editCategory({'id':this.classData.id,'name': this.classData.name, sort: this.classData.sort}).then(res => {if (res.code === 1) {this.$message.success('分类修改成功!')this.classData.dialogVisible = falsethis.handleQuery()} else {this.$message.error(res.msg || '操作失败')}}).catch(err => {this.$message.error('请求出错了:' + err)})} else {this.$message.error('排序只能输入数字类型')}} else {this.$message.error('请输入分类名称或排序')}}// 修改接口const editCategory = (params) => {return $axios({url: '/category',method: 'put',data: { ...params }})}
</script>

后端处理请求

根据用户提交的json格式的菜品/套餐分类信息,去数据表中更新对应的菜品/套餐记录

@PutMapping
public Result<String> update(@RequestBody Category category) {log.info("修改分类信息为:{}", category);categoryService.updateById(category);return Result.success("修改分类信息成功");
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/155280.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Apache DolphinScheduler 3.0.0 升级到 3.1.8 教程

安装部署的流程可参考官网的文档 Version 3.1.8/部署指南/伪集群部署(Pseudo-Cluster) https://dolphinscheduler.apache.org/zh-cn/docs/3.1.8/guide/installation/pseudo-cluster 本文开始之前&#xff0c;我先补充说明一下升级 Apache DolphinScheduler 的几个关键点 元数…

低代码服务商,中小型数字化软件服务商的新出路

数字化时代大背景下&#xff0c;企业信息化向数字化转型成为所有企业发展的必由之路&#xff0c;企业在对业务模式、流程、组织形式、信息技术等方面进行重新定义时&#xff0c;软件必然参与价值创造的全过程&#xff0c;这势必驱使软件成为推动数字化转型的“引擎”&#xff0…

debian 12 配置

1. 修改apt源 修改apt源为http版本 # 默认注释了源码镜像以提高 apt update 速度&#xff0c;如有需要可自行取消注释 deb http://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware # deb-src http://mirrors.tuna.tsinghua.edu.cn/d…

文化传承与数字技术的完美结合:十八数藏的新纪元

在这数字化的时代&#xff0c;十八数藏犹如一座连接过去与未来的桥梁&#xff0c;展现出文化传承与数字技术完美结合的新纪元。十八数藏以其独特的视角&#xff0c;将传统文化注入现代数字技术的脉络&#xff0c;呈现出一幅文化传承的全新画卷。 十八数藏的文化传承并不是简单的…

软件测评中心进行安全测试有哪些流程?安全测试报告如何收费?

在当今数字化时代&#xff0c;软件安全测试是每个软件开发团队都不能忽视的重要环节。安全测试是指对软件产品进行系统、全面的安全性评测与检测的过程。它旨在发现并修复软件中存在的漏洞和安全隐患&#xff0c;以确保软件能够在使用过程中保护用户的数据和隐私不被非法访问和…

深入了解Java 8 新特性:Stream流的实践应用(二)

阅读建议 嗨&#xff0c;伙计&#xff01;刷到这篇文章咱们就是有缘人&#xff0c;在阅读这篇文章前我有一些建议&#xff1a; 本篇文章大概8000多字&#xff0c;预计阅读时间长需要10分钟&#xff08;不要害怕字数过多&#xff0c;其中有一大部分是示例代码&#xff0c;读起…

RAAGR2-Net:一种使用多个空间帧的并行处理的脑肿瘤分割网络

RAAGR2-Net: A brain tumor segmentation network using parallel processing of multiple spatial frames RAAGR2-Net&#xff1a;一种使用多个空间帧的并行处理的脑肿瘤分割网络背景贡献实验N4 bias-field-correction 数据预处理Z-score and re-sampling Z-score归一化&#…

redis高可用---持久化

redis高可用 在集群当中有一个非常重要的指标&#xff0c;提供正常服务的时间的百分比(365天) 99.9%&#xff0c;redis高可用含义更广泛&#xff0c;支持服务是指标之一&#xff0c;数据容量扩展&#xff0c;数局的安全性。&#xff08;容量、安全性&#xff09; redis中实现高…

数据仓库模式之详解 Inmon 和 Kimball

目录 一、前言 二、企业信息工厂&#xff08;Inmon&#xff09; 2.1 概念 2.2 主要组件 2.3 流程 三、多维数据仓库&#xff08;Kimball&#xff09; 3.1 概念 3.2 核心组件 3.3 流程 四、异同及用途对比 4.1 异同对比 4.2 特征比较 一、前言 大部分关于数据仓库构建…

小微初创企业,如何利用媒体宣传快速成长

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 对于小微初创企业来说&#xff0c;利用媒体宣传可以快速提升品牌知名度、扩大影响力&#xff0c;进而促进企业的成长。 1.确定宣传目标&#xff1a;是增加销售、提升品牌知名度、还是推…

JVM对象创建与内存分配

对象的创建 对象创建的主要流程&#xff1a; 类加载推荐博客&#xff1a;JVM类加载机制详解 类加载检查 虚拟机遇到一条new指令时&#xff0c;首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用&#xff0c;并且检查这个符号引用代表的类是否已被加载、解析…

Failed to load resource: net::ERR_UPLOAD_FILE_CHANGED 谷歌浏览器就会有这个问题 其他的浏览器没有

Failed to load resource: net::ERR_UPLOAD_FILE_CHANGED 10 10: Difficulties in file uploading through all browsers and applications

mac添加Chrome插件的方法

如果是.crx的插件 更改后缀crx为zip 后续步骤同下文.zip文件 如果是.zip的插件 使用终端进行解压 注意不要用解压工具解压&#xff0c;一定要用终端&#xff0c;命令行解压 // 进入到“插件名.zip”文件的目录下&#xff0c;输入下面命令&#xff1a; unzip 插件名.zip -…

「ResNet-18」70 个犬种的图片分类

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…

LeetCode【45】跳跃游戏2

题目&#xff1a; 思路&#xff1a; 注意和跳跃游戏【55】不同的是&#xff0c;题目保证可以跳到nums[n-1];那么每次跳到最大即可 代码&#xff1a; public class LeetCode45 {public static int jump(int[] nums) {int jumps 0;int currentEnd 0;int farthest 0;for(int…

Android Serializable / Parcelable

Serializable 序列化,将对象转为二进制序列 Parcelable 不是序列化,属于进程间通信,不需要IO/操作,没有拷贝内存的操作, Object -> ShareMemory -> Object 不需要IO,使用内存共享等方式 Kotlin inline fun 内联函数 TCP协议将数据包拆分,进行发送,保证网络数据的可…

基于纹理特征的kmeas聚类的图像分割方案

Gabor滤波器简介 在图像处理中&#xff0c;以Dennis Gabor命名的Gabor滤波器是一种用于纹理分析的线性滤波器&#xff0c;本质上是指在分析点或分析区域周围的局部区域内&#xff0c;分析图像中是否存在特定方向的特定频率内容。Gabor滤波器的频率和方向表示被许多当代视觉科学…

二十一、数组(3)

本章概要 Arrays的setAll方法增量生成 Arrays的setAll方法 在Java 8中&#xff0c; 在RaggedArray.java 中引入并在 ArrayOfGenerics.java.Array.setAll() 中重用。它使用一个生成器并生成不同的值&#xff0c;可以选择基于数组的索引元素&#xff08;通过访问当前索引&…

Android项目更新依赖和打包步骤和问题汇总

目录 1、Android 项目打包&#xff0c;32位包升级到64位包问题一&#xff1a;ERROR: Conflicting configuration : armeabi-v7a,x86-64,arm64-v8a,x86 in ndk abiFilters cannot be present when splits abi filters are set : x86,armeabi-v7a,arm64-v8a 2、Android项目依赖升…

pytest-base-url插件之配置可选的项目系统URL

前言 ①当我们的自动化代码完成之后&#xff0c;通常期望可以在不同的环境进行测试&#xff0c;此时可以将项目系统的URL单独拿出来&#xff0c;并且可以通过pytest.ini配置文件和支持pytest命令行方式执行。 ② pytest-base-url 是一个简单的pytest插件&#xff0c;它通过命…