SpringBoot + Vue front-end and back-end separation project actual combat || Five: Follow-up of user management function

Series of articles:
SpringBoot + Vue front-end and back-end separation project practice || One: Vue front-end design
SpringBoot + Vue front-end separation project practice || Two: Spring Boot backend and database connection
SpringBoot + Vue front-end separation project practice || Three: Spring Boot backend and Vue frontend connection
SpringBoot + Vue front-end and front-end separation project practice || Four: User management function implementation
SpringBoot + Vue front-end separation project practice || Five: User management function follow-up

Review and Outlook

Previously, we introduced the data display of the user management interface. Next, we need to add, modify, and delete users.
Insert image description here
Insert image description here

Implementation of new user functions

Front-end implementation

When user.vuewriting the code for the pop-up dialog box, the code also comes from the Element-UI component
Insert image description here

<!-- 用户信息编辑对话框 -->
<!-- :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>

This dialog box has three important properties:
Insert image description here

  • Red: The operation of closing the dialog box. After closing the dialog box, you need to clear the form and clear the validation rules of the form. This part of the code is written methodsin
    Insert image description here
  • Orange: It is the title of the pop-up dialog box. Here we set the new dialog box and the edit dialog box to be the same. According to different operations, different names are displayed. Because it is a
    Insert image description here
    Insert image description here
    variable :title, it needs to be registered.
    Insert image description here
  • White: Modify whether the pop-up window is displayed. In fact, the pop-up window is always there. It is only displayed after clicking the button, and then hidden after closing. It also needs to be registered as a variable, so make it invisible first.
    Insert image description here

Three properties of the form
Insert image description here

  • Red: The first-level variable name of the form data. If you want to access the data inside userForm.username, this is the field in the input v-model. This field should be consistent with the back-end entity class name. At the same time, the fields in the item propare also consistent with the backend.

  • Orange: refVariable name used for form verification, clearFormused in the previous section

  • Bai: Define form verification rules. The following code can Element-UIbe found on the official website. The code is written datain returnthe area, not in methods.
    Insert image description here

    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' }
         ],
       },
    

    Insert image description here

    There are two custom rule verifications in the rule verification: checkEmail, checkPhone, these two are regular expressions. You can search the verification rules of email and phone in Baidu. You can use them here directly. Note that these two verification rules are written in data, not data\returnin
    Insert image description here

     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();    // 效验成功
     };
    

The entire form is the red part in the picture below
Insert image description here

  • Orange: It is the variable name of the form receiving field, which is consistent with the back-end database entity class.
  • White: When modifying user information, do not give the opportunity to change the password. However, when adding a new user, an initial password will be set, so a judgment needs to be made. If you want to modify a user, then the user will have an ID. If it userForm.idexists, it means you are modifying the user. The user's information will be displayed and then modified.
    Note: All attributes in the entity class are passed from the backend, and userForm also receives all attributes. Only name, email, etc. are displayed. The rest of the attributes are not displayed and are still accessible.

submit button
Insert image description here

  • Orange: Click 取消the button to set the display property of the dialog box falseto invisible
  • White: 保存Function triggered by clicking the button: saveUser, the operation process of this function has been explained in the comments
    Insert image description here
    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;
         }
       });
     },
    

The vue code of all dialog forms is as follows

<!-- 用户信息编辑对话框 -->
<!-- :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>

Front-end interface implementation

The files of the front-end interface are in the path src\api\userManage.js. Please note that the corresponding methods for adding, deleting, modifying and checking are 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'
    });
  },


}

Backend implementation

The backend code is UserController.javain

New users

Insert image description here

	 // 前端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("新增用户成功");
    }

The corresponding front end is as follows:
Insert image description here

Encryption operation:
There is a password encryption function in the new user. When the user password is written to the database, it is encrypted and salted, as shown below. The plain text of the password is123456
Insert image description here

(Salting: For the same password combination, the ciphertext is also different)

Add dependencies in pom.xml:

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

Register in startup classBean
Insert image description here

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

UserControllerRegister variables in
Insert image description here

Modify the login
logic. After the password is encrypted, you cannot simply match the database password when logging in. A decryption matching process is required.
Modify the back-end file.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;
}

At this point, the new user function is completed


Modify user

Insert image description here

	@PutMapping
    public Result<?> updateUser(@RequestBody User user){
    
    
        // @RequestBody 用于json转为实体对象

        user.setPassword(null);
        userService.updateById(user);
        return Result.success("修改用户成功");
    }

The corresponding front-end is as follows:
Insert image description here

delete users

Insert image description here

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

The front end is as follows:
Insert image description here

In company project management, logical deletion is generally used, which does not actually delete the records in the database, but sets a field in the data table deletedas a mark. 0 means not deleted, 1 means deleted
Insert image description here

resources\application.ymlAdd configuration in

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

In this way, Spring will automatically splice SQL statements when queryingWHERE deleted = 0
Insert image description here

After configuration, after 删除oioi用户前the database
Insert image description here
Insert image description here
Insert image description here
is deleted, the last field becomes 1


Find users based on id and display data in the modification form

Insert image description here

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

The corresponding front-end is as follows:
Insert image description here

Finished spreading flowers! ! !

Guess you like

Origin blog.csdn.net/qq_56039091/article/details/131429258