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

news2024/12/23 7:59:58

系列文章:
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:{    // 传给后端的参数,对应后端的 @RequestParam
        pageNo: 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}`,    // 写法二 ,对应后端的 @PathVariable
      method:'get'
    });
  },

  deleteUserById(id){
    return request({
      url:`/user/${id}`,    // 对应后端的 @PathVariable
      method:'delete'
    });
  },


}

后端实现

后端代码在UserController.java

新增用户

在这里插入图片描述

	 // 前端addUser方法的url就是"/user" 故此处无url
    @PostMapping
    public 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-core
    return 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,将用户信息存入redis
    if (loginUser != null &&
            passwordEncoder.matches(user.getPassword(), loginUser.getPassword())    // 匹配加密密码
    ) {
        // 用UUID,终极方案是jwt
        String key = "user:" + UUID.randomUUID();

        // 存入redis
        loginUser.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
    // 并将用户信息存入redis
    return null;
}

至此,新增用户功能完毕


修改用户

在这里插入图片描述

	@PutMapping
    public 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.coloradmin.cn/o/695218.html

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

相关文章

vscode调试python配置

{// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。// 欲了解更多信息&#xff0c;请访问: https://go.microsoft.com/fwlink/?linkid830387"version": "0.2.0","configurations": [{"name": "Python: 当前文…

域渗透(1)

域基础信息搜集 ping 域名ipconfig /all 判断当前是否在域环境中&#xff0c;看dns后缀和dns服务器net view 查看本工作组/域环境中的设备关闭防火墙开启服务net view /domain 查询域数量net view | net view /domain:域名 查询主机数量net group /domain 域控组别信…

使用el-tree实现不同区域的拖拽功能时遇到的坑点

问题再现 利用el-tree实现在两个区域的拖拽&#xff0c;1.树上的拖拽排序&#xff0c;2.将树上节点拖拽到画布上。 在将节点拖拽到画布上的时候&#xff0c;只要在树上移动过&#xff0c;松开鼠标的时候&#xff0c;树上的拖拽排序功能也生效了&#xff0c;那么如何使这两个拖…

蓝海卓越计费管理系统 download.php 任意文件读取漏洞

0x01、漏洞描述 蓝海卓越计费管理系统 download.php文件存在任意文件读取漏洞&#xff0c;攻击者通过 …/ 遍历目录可以读取服务器上的敏感文件 0x02、漏洞影响 蓝海卓越计费管理系统 0x03、fofa title“蓝海卓越计费管理系统” 0x04、漏洞复现 登录页面如下&#xff1a…

shell中快速遍历文件下指定的内容

1.举例 遍历当前目录下所有Makefile文件&#xff0c;找到内容适配CONFIG_SMP的所有Makefile find -type f -name Makefile | xargs grep "CONFIG_SMP" 2.find命令 3.xargs命令 3.1. 命令由来 xargs &#xff08;英文全拼&#xff1a; eXtended ARGuments&#xff…

关于Idea中springboot热部署,html,js保存不起作用

a、引入依赖&#xff1a; <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </depe…

浅谈智能还书车

智能还书车是一种新型的智能化设备&#xff0c;配备触摸显示屏或简单操作的人机交流界面、图形界面&#xff0c;通过协议或其他网络及专用接口与图书馆自动化系统数据相连接&#xff0c;由读者自行对图书进行快速归还&#xff0c;读者把图书放到书车上&#xff0c;系统自动对图…

2. 线性模型

b站刘二老师pytorch深度学习课程&#xff1a;https://www.bilibili.com/video/BV1Y7411d7Ys?p2&vd_sourceb17f113d28933824d753a0915d5e3a90 如果每周学习4个小时&#xff0c;那能够获得什么成绩&#xff1f; y已知的是采样得到的数据&#xff0c;属于训练集&#xff08;t…

使用 css 禁用 input 控件实现 disable 效果

文章目录 需求分析代码 需求 使用 css 禁用 input 控件实现 disable 效果 分析 在 js 中&#xff0c;我们使用以下方法来阻止input,select,checkbox的默认事件&#xff0c;如 javascript event.preventDefault() event.stopPropagation()但在 css 中&#xff0c;我们可以设置对…

Android App的几个核心概念

Application启动 点击桌面图标启动App(如下流程图) 针对以上流程图示&#xff1a; ActivityManagerService#startProcessLocked()Process#start()ActivityThread#main()&#xff0c;入口分析的地方ActivityThread#attach()&#xff0c;这个里面的逻辑很核心 ActivityManagerS…

20230621 taro+vue3+webpack5+antdv时,在vue文件中特定组件时,devH5环境报错

问题 在某个vue文件下 import { notification } from ant-design-vue;然后在终端开始 yarn dev:h5在浏览器看效果 回出现以下错误 Uncaught (in promise) TypeError: __webpack_require__.hmd is not a functionat ./node_modules/.taro/h5/prebundle/ant-design-vue.js原因…

提高客户体验:智能客服外包服务的优势

随着科技的发展&#xff0c;智能客服外包服务越来越受到企业的青睐。这种服务能够帮助企业提高客户体验&#xff0c;减少客服成本&#xff0c;提高工作效率。本文将从技术、用户体验等方面阐述智能客服外包服务的优势。 人工智能技术 智能客服外包服务采用了一系列的技术手段&…

自然语言处理库NLTK的初步环境配置和使用例子

NLTK的基本介绍见此&#xff0c; 了解自然语言处理_bcbobo21cn的博客-CSDN博客 先安装python&#xff1b;然后用pip命令安装nltk&#xff1b; 然后进入python&#xff0c;下载nltk的数据包&#xff1b;输入下图语句&#xff0c;弹出一个框&#xff0c; 一般选择 all&#xff…

PHP 实验室设备系统mysql数据库web结构apache计算机软件工程网页wamp

一、源码特点 PHP 实验室设备系统 是一套完善的web设计系统&#xff0c;对理解php编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 代码下载 https://download.csdn.net/download/qq_41221322/87959348https://downlo…

Kaggle 数据竞赛 | ICR - 鉴定与年龄相关的疾病

文章目录 一、前言二、主要内容1. 评估2. 时间线3. 奖金4. 代码要求 三、总结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、前言 使用机器学习技术&#xff0c;通过匿名健康特征的测量数据来检测疾病。 比赛目标 本次比赛的目标是预测一个人是…

华为云Classroom一站式教学实践平台,开启云端教学新征程

随着高考落下帷幕&#xff0c;各高校将迎来新一届大学新生入学&#xff0c;他们的学长学姐们经过四年的学习&#xff0c;也即将步入社会&#xff0c;迈向一段新的人生旅程。 在这里小智先祝大家未来一切顺意&#xff0c;不忘初心&#xff0c;大鹏一日同风起&#xff0c;扶摇直…

win10环境下php安装thinkPHP5的曲线方式

win10环境下php安装thinkPHP5的曲线方式 强调一下在win10环境安装thinkPHP5需要使用Composer。 首先是thinkphp的教程&#xff1a;https://www.kancloud.cn/manual/thinkphp5/118006 你就会发现很坑逼 安装Composer的时候一种报错&#xff0c;就是php.ini文件错误。网上说什么…

Unity内置渲染管线升级URP教程

简介 URP全称为Universal Render Pipeline(通用渲染管线)&#xff0c;可以提供更加灵活的渲染方案&#xff0c;通过添加Render Feature实现各种渲染效果。并且可以针对移动平台进行专门的优化&#xff0c;同时还提供了SRPBatcher提高渲染效率。Unity的一些工具&#xff0c;比如…

客户关系管理系统有哪些?5款客户关系管理软件评测

客户关系管理系统是一种企业与客户之间的交互平台&#xff0c;它将客户的需求、市场环境、企业的发展战略等融入到整个业务流程中&#xff0c;在企业和客户之间建立起一个共享的资源库&#xff0c;使企业对客户的了解更深更全面&#xff0c;进而实现与客户的深入互动&#xff0…

C#创建窗体应用程序

1、新建项目&#xff0c;选择窗体应用 2、打开相关视图 工具箱&#xff1a;将工具箱中的控件直接拖拽到界面中&#xff0c;会自动生成对用的控件。 属性&#xff1a;可以设置控件的相关属性&#xff0c;包括事件&#xff0c;双击 3、设计应用界面 4、新建一个交互窗口 5、在登…