SpringBoot + Vue前后端分离项目实战 || 五:用户管理功能后续

系列文章:
SpringBoot + Vue前后端分离项目实战 || 一:Vue前端设计
SpringBoot + Vue前后端分离项目实战 || 二:Spring Boot后端与数据库连接
SpringBoot + Vue前后端分离项目实战 || 三:Spring Boot后端与Vue前端连接
SpringBoot + Vue前后端分离项目实战 || 四:用户管理功能实现
SpringBoot + Vue前后端分离项目实战 || 五:用户管理功能后续

文章目录

    • 回顾与展望
    • 新增用户功能实现
      • 前端实现
      • 前端接口实现
    • 后端实现
      • 新增用户
      • 修改用户
      • 删除用户
      • 根据id查找用户,显示数据在修改表单中
    • 完结撒花!!!

回顾与展望

之前介绍了用户管理界面的数据展示,接下来需要做新增、修改、删除用户的功能
在这里插入图片描述
在这里插入图片描述

新增用户功能实现

前端实现

user.vue编写弹窗对话框的代码,该代码同样来自Element-UI组件
在这里插入图片描述

<!-- 用户信息编辑对话框 -->
<!-- :title 加了冒号就变成一个变量,属性绑定了,后面的东西需要在data中说明 -->
<el-dialog @close="clearForm" :title="title" :visible.sync="dialogFormVisible"><el-form :model="userForm" ref="userFormRef" :rules="rules"><el-form-item label="用户名" prop="username" :label-width="formLabelWidth"><el-input v-model="userForm.username" autocomplete="off"></el-input></el-form-item><el-form-item v-if="userForm.id == null || userForm.id == undefined"label="登录密码" prop="password" :label-width="formLabelWidth"><el-input type="password" v-model="userForm.password" autocomplete="off"></el-input></el-form-item><el-form-item label="联系电话" prop="phone" :label-width="formLabelWidth"><el-input v-model="userForm.phone" autocomplete="off"></el-input></el-form-item><el-form-item label="用户状态" :label-width="formLabelWidth"><el-switch v-model="userForm.status" :active-value="1":inactive-value="0"active-color="#13ce66" inactive-color="#ff4949"></el-switch></el-form-item><el-form-item label="电子邮件" prop="email" :label-width="formLabelWidth"><el-input v-model="userForm.email" autocomplete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="dialogFormVisible = false">取 消</el-button><el-button type="primary" @click="saveUser">确 定</el-button></div>
</el-dialog>

该对话框有三个比较重要的属性
在这里插入图片描述

  • 红色:关闭对话框的操作,关闭对话框后需要清空表单,并且清空表单的效验规则,这部分代码写在methods
    在这里插入图片描述
  • 橙色:为弹出对话框的标题,此处我们将新增对话框和编辑对话框设置为同一个,根据不同的操作,显示不同的名称
    在这里插入图片描述
    在这里插入图片描述
    因为:title是变量,所以需要注册
    在这里插入图片描述
  • 白色:修改弹窗是否显示,其实弹窗一直都在,只是点击按钮后,将其显示出来,关闭后又将其隐藏起来,同样身为变量需要注册,先让其不可见
    在这里插入图片描述

表单的三个属性
在这里插入图片描述

  • 红:表单数据的一级变量名,若要访问里面的数据可用userForm.username,这是input中的v-model字段,该字段应与后端实体类名一致。 同时item中prop字段也与后端一致

  • 橙:ref用于表单校验时的变量名,前面clearForm中有用到

  • 白:定义表单校验规则,如下代码可在Element-UI官网中找到,代码写在datareturn区域内,不是methods内
    在这里插入图片描述

    rules:{   // 表单校验username: [{ required: true, message: '请输入用户名', trigger: 'blur' },{ min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }],password: [{ required: true, message: '请输入初始密码', trigger: 'blur' },{ min: 6, max: 16, message: '长度在 6 到 16 个字符', trigger: 'blur' }],email: [{ required: true, message: '请输入电子邮件', trigger: 'blur' },{ validator: checkEmail, trigger: 'blur' }],phone: [{ validator: checkPhone, trigger: 'blur' }],},
    

    在这里插入图片描述

    规则校验中有两个是自定义的规则校验:checkEmailcheckPhone,这两个为正则表达式,可百度搜索邮箱、电话的效验规则,此处拿过来直接用。注意这两个校验规则写在data里,而不是data\return
    在这里插入图片描述

     var checkEmail = (rule, value, callback) => {var reg = /^([a-zA-Z\d][\w-]{2,})@(\w{2,})\.([a-z]{2,})(\.[a-z]{2,})?$/if (!reg.test(value)) {return callback(new Error('邮箱格式错误'));}callback();   // 效验成功};var checkPhone = (rule, value, callback) => {var reg = /^[1]+\d{10}$/if (!reg.test(value)) {return callback(new Error('请输入正确的手机号码'));}callback();    // 效验成功};
    

表单整体为下图红色部分
在这里插入图片描述

  • 橙色:为表单接收字段的变量名,与后端数据库实体类保持一致
  • 白色:在修改用户信息时,不给修改密码的机会。但是新增用户时,会设置初始密码,所以需要做一个判断。如果为修改用户,那么该用户会有一个id,通过userForm.id访问,存在的话说明是修改用户,会将该用户的信息展示出来,再进行修改。
    注意:后端传过来的是实体类中的所有属性,userForm也接收了所有属性,只是展示出来的只有姓名、邮箱等,其余的属性没有展示,仍然可访问

提交按钮
在这里插入图片描述

  • 橙色:点击取消按钮,将对话框的显示属性设为false,不可见
  • 白色: 点击保存按钮触发的函数:saveUser,此函数的操作流程在注释中已说明
    在这里插入图片描述
    saveUser(){// 触发表单验证this.$refs.userFormRef.validate((valid) => {if (valid) {  // 验证通过// 数据传给后端userApi.saveUser(this.userForm).then(response=>{// 提交成功后的操作// 插入数据成功提示this.$message({message: response.message,type: 'success'});// 关闭对话框,清除表单数据this.dialogFormVisible = false;this.clearForm();// 刷新表格this.getUserList();});} else {  // 验证失败console.log('error submit!!');return false;}});},
    

所有对话框表单的vue代码如下

<!-- 用户信息编辑对话框 -->
<!-- :title 加了冒号就变成一个变量,属性绑定了,后面的东西需要在data中说明 -->
<el-dialog @close="clearForm" :title="title" :visible.sync="dialogFormVisible"><el-form :model="userForm" ref="userFormRef" :rules="rules"><el-form-item label="用户名" prop="username" :label-width="formLabelWidth"><el-input v-model="userForm.username" autocomplete="off"></el-input></el-form-item><el-form-item v-if="userForm.id == null || userForm.id == undefined"label="登录密码" prop="password" :label-width="formLabelWidth"><el-input type="password" v-model="userForm.password" autocomplete="off"></el-input></el-form-item><el-form-item label="联系电话" prop="phone" :label-width="formLabelWidth"><el-input v-model="userForm.phone" autocomplete="off"></el-input></el-form-item><el-form-item label="用户状态" :label-width="formLabelWidth"><el-switch v-model="userForm.status" :active-value="1":inactive-value="0"active-color="#13ce66" inactive-color="#ff4949"></el-switch></el-form-item><el-form-item label="电子邮件" prop="email" :label-width="formLabelWidth"><el-input v-model="userForm.email" autocomplete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="dialogFormVisible = false">取 消</el-button><el-button type="primary" @click="saveUser">确 定</el-button></div>
</el-dialog>

前端接口实现

前端接口的文件在路径src\api\userManage.js中,注意增删改查对应的方法分别是post/delete/put/get

import request from '@/utils/request'export default{getUserList(searchModel){return request({url:'/user/list',method:'get',params:{    // 传给后端的参数,对应后端的 @RequestParampageNo: searchModel.pageNo,pageSize: searchModel.pageSize,username: searchModel.username,phone: searchModel.phone,}});},addUser(user){return request({url:'/user',method:'post',data:user   // 传回后端的实体数据});},saveUser(user){if(user.id == null || user.id == undefined){return this.addUser(user);}else{return this.updateUser(user);}},updateUser(user){return request({url:'/user',method:'put',data:user});},getUserById(id){return request({// url:'/user/' + id,   // 写法一url:`/user/${id}`,    // 写法二 ,对应后端的 @PathVariablemethod:'get'});},deleteUserById(id){return request({url:`/user/${id}`,    // 对应后端的 @PathVariablemethod:'delete'});},}

后端实现

后端代码在UserController.java

新增用户

在这里插入图片描述

	 // 前端addUser方法的url就是"/user" 故此处无url@PostMappingpublic Result<?> addUser(@RequestBody User user){// @RequestBody 用于json转为实体对象// 做了加盐处理user.setPassword(passwordEncoder.encode(user.getPassword()));userService.save(user);return Result.success("新增用户成功");}

与对应的前端如下:
在这里插入图片描述

加密操作
新增用户中有个密码加密功能,将用户密码写入数据库时,对其加密加盐,如下图,密码明文是123456
在这里插入图片描述

(加盐:针对同一个密码组合,密文也是不同的)

pom.xml中添加依赖:

<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-core</artifactId>
</dependency>

在启动类里注册Bean
在这里插入图片描述

@Bean
public PasswordEncoder passwordEncoder(){// 密码加密的工具类,来自依赖spring-security-corereturn new BCryptPasswordEncoder();
}

UserController里注册变量
在这里插入图片描述

修改登录逻辑
密码加密后,登录时不能简单匹配数据库的密码,需要有个解密匹配过程
修改后端文件service\impl\UserServiceImpl

@Override
public Map<String, Object> login(User user) {// 根据用户名查询LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();wrapper.eq(User::getUsername, user.getUsername());User loginUser = this.baseMapper.selectOne(wrapper);// 结果不为空,并且密码与数据库解密后的密码匹配,生成token,将用户信息存入redisif (loginUser != null &&passwordEncoder.matches(user.getPassword(), loginUser.getPassword())    // 匹配加密密码) {// 用UUID,终极方案是jwtString key = "user:" + UUID.randomUUID();// 存入redisloginUser.setPassword(null);    // 设置密码为空,密码没必要放入redisTemplate.opsForValue().set(key, loginUser,10, TimeUnit.MINUTES);   // timeout为登录时间// 返回数据Map<String, Object> data = new HashMap<>();data.put("token",key);return data;}// 结果不为空,生成token,前后端分离,前端无法使用session,可以使用token// 并将用户信息存入redisreturn null;
}

至此,新增用户功能完毕


修改用户

在这里插入图片描述

	@PutMappingpublic Result<?> updateUser(@RequestBody User user){// @RequestBody 用于json转为实体对象user.setPassword(null);userService.updateById(user);return Result.success("修改用户成功");}

对应的前端如下:
在这里插入图片描述

删除用户

在这里插入图片描述

	@DeleteMapping("/{id}")public Result<?> deleteUserById(@PathVariable("id") Integer id){userService.removeById(id);return Result.success("删除用户成功");}

前端如下:
在这里插入图片描述

在公司项目管理中,一般都是使用逻辑删除,并不是真正删除数据库里的记录,而是在数据表中设置一个字段deleted做一个标记位。0表示未删除,1表示已删除
在这里插入图片描述

resources\application.yml中添加配置

mybatis-plus:global-config:db-config:logic-delete-field: deleted # 全局逻辑删除的实体字段名,与数据库的字段名一致logic-delete-value: 1 # 逻辑已删除值(默认为 1)logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

这样,Spring会在查询时自动拼接SQL语句WHERE deleted = 0
在这里插入图片描述

配置好后,删除oioi用户前的数据库
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
删除后,最后一个字段变为1


根据id查找用户,显示数据在修改表单中

在这里插入图片描述

	@GetMapping("/{id}")public Result<User> getUserById(@PathVariable("id") Integer id){User user = userService.getById(id);return Result.success(user);}

对应的前端如下:
在这里插入图片描述

完结撒花!!!

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

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

相关文章

数字图像处理(三)

目录 实验六、图像分割方法 实验七、图像识别与分类 实验六、图像分割方法 一、实验目的 了解图像分割技术相关基础知识&#xff1b;掌握几种经典边缘检测算子的基本原理、实现步骤理解阈值分割、区域分割等的基本原理、实现步骤。理解分水岭分割方法的基本原理、实现方法。…

在 Mac 上安装 K8S

本篇文章将介绍如何在 Mac 上使用 minikube 搭建单机版的 Kubernetes。 安装步骤 安装 Docker 安装 docker 主要是用于提供容器引擎。直接下载安装即可。 下载地址 安装 Kubectl 推荐使用 home brew 安装 brew install kubectl可以使用下面的命令查看是否已经安装完毕 …

css实现鼠标悬停时滑出层提示

css实现鼠标悬停时滑出层提示的方法介绍 这是一个简单的鼠标悬停提示特效&#xff0c;类似于alt标签&#xff0c;不过这一种是用纯CSS实现&#xff0c;扩展性好&#xff0c;而且在提示的层里可以加入图片或其它布局&#xff0c;这个要根据你的需要了。 代码如下: <!DOCTYPE…

Flink基础概念及常识

1.flink入门 官方定义&#xff1a;Apache Flink是一个框架和分布式处理引擎&#xff0c;用于在无边界和有边界数据流上进行有状态的计算&#xff0c;Flink能在所有常见集群环境中运行&#xff0c;并能以内存速度和任意规模进行计算。 简言之&#xff0c;Flink是一个分布式的计…

Spring相关API

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;JavaEE、Spring SpringAPI 1、继承体系2、 getBean() 1、继承体系 上述继承体系中的主要类和接口包括&#xff1…

[Spec] WiFi P2P Discovery

学习资料&#xff1a;Android Miracast 投屏 目录 学习资料&#xff1a;Android Miracast 投屏 P2P discovery Introduction Device Discovery procedures Listen State Search State Scan Phase Find Phase 总结 P2P discovery Introduction P2P发现使P2P设备能够快速…

SC7514运算放大器(OPA)可pin对pin兼容AD8694

SC751X 系列轨至轨 CMOS 运算放大器针对低电压单电源运行进行了优化。轨至轨输入和输出、低噪声(5nV/√Hz) 和高速运行 (38MHz, 22V/μs) 使得运算放大器非常适合驱动模数 (A/D) 转换器。可pin对pin兼容AD8694。而且也适用于手机功率放大器 (PA) 控制环路和视频处理(75Ω 驱动能…

如何清除浏览器的 DNS 缓存 (Chrome, Firefox, Safari)

如何清除浏览器的 DNS 缓存 (Chrome, Firefox, Safari) Chrome Chromium Edge Firefox Safari clear DNS Cache, flush DNS cache 请访问原文链接&#xff1a;https://sysin.org/blog/clear-browser-dns-cache/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。…

macOS FreeBSD 如何刷新 DNS 缓存

macOS FreeBSD 如何刷新 DNS 缓存 全文&#xff1a;如何刷新 DNS 缓存 (macOS, Linux, Windows) Unix Linux Windows 如何刷新 DNS 缓存 (macOS, FreeBSD, RHEL, CentOS, Debian, Ubuntu, Windows) 请访问原文链接&#xff1a;https://sysin.org/blog/how-to-flush-dns-cach…

无迹卡尔曼滤波在目标跟踪中的作用(一)

在前一节中&#xff0c;我们介绍了扩展卡尔曼滤波算法EKF在目标跟踪中的应用&#xff0c;其原理是 将非线性函数局部线性化&#xff0c;舍弃高阶泰勒项&#xff0c;只保留一次项 &#xff0c;这就不可避免地会影响结果的准确性&#xff0c;除此以外&#xff0c;实际中要计算雅各…

机器学习李宏毅学习笔记36

文章目录 前言Meta learning应用总结 前言 Meta learning&#xff08;二&#xff09;应用方向 Meta learning应用 回顾gradient descen Θ0&#xff08;initial的参数&#xff09;是可以训练的&#xff0c;一个好的初始化参数和普通的是有很大差距的。可以通过一些训练的任务…

2 Prometheus 简介

目录 1. 起源 2. Prometheus 架构 2.1 指标收集 2.2 服务发现 2.3 聚合和警报 2.4 查询数据 2.5 服务自治 2.6 冗余和高可用性 2.7 可视化 3. Prometheus数据模型 3.1 指标名称 3.2 标签 3.3 采样数据 3.4 符号表示 3.5 保留时间 4. 安全模型 5. Prometheus生态…