学员管理系统- 项目跟进day04 角色管理与权限设置

        在Vue组件中,data函数返回的是一个对象,该对象中包含所有与该组件相关的数据。在这段代码中,data函数返回一个对象,它包含了该组件所需的所有数据,包括currentRow、roleList、roleFormVisible、roleAuthVisible、role、roleRules等等这些数据是组件的重要部分,它们描述了组件的状态和属性,并且能够驱动组件的UI交互行为。提前声明这些数据而不是在需要它们时动态声明,允许Vue在组件渲染和更新时即时访问和修改这些数据,以保持UI状态和行为的一致性。

        此外,由于这些数据是响应式的,它们的变化会自动触发Vue的更新机制,导致组件渲染以反映最新的数据状态。所以在组件中提前声明并初始这些数据很重要,可以使代码更容易维护和理解,避免了无意修改应用程序状态的风险。

1 后端设置添加角色接口

在后端服务器中的router的index.js中进行设置

接收前端地址/manage/role/add发出的post请求并处理

    // 添加角色
    router.post("/manage/role/add",(req,res)=>{
        const {name} = req.body
        RoleModel.create({name}).then(role=>{
            res.send({status:0,data:role})
        }).catch(error=>{
            console.log("添加角色异常",error);
            res.send({status:1,msg:'添加角色异常,请重试'})
        })
    })

RoleModel.js中定义了用户信息规则,故需使用RoleModel.create().then创建

同时将name保存到数据库中

RoleModel.create方法是在RoleModel.js中定义的,并通过mongoose.model方法创建了一个名为roles的模型RoleModel.js中,定义了角色的数据结构,包括nameauth_nameauth_timecreate_timemenus等字段,并指定了各个字段的类型、验证规则和默认值。当调用RoleModel.create({name})时,会使用name参数创建一个新的角色实例并保存到数据库中。

const mongoose = require('mongoose')

const roleSchema = new mongoose.Schema({
    name:{type:String,required:true},
    auth_name:String,
    auth_time:Number,
    create_time:{type:Number,default:Date.now},
    menus:Array
})

const RoleModel = mongoose.model('roles',roleSchema)

module.exports = RoleModel

设置完可以在postman中发送post请求进行测试  

2 后端接口设置完成后需要在前端api的role.js中创建添加角色的功能来发送post请求到后端

    // 添加角色
    addRole(name){
        return request({
            url:'/manage/role/add',
            method:'post',
            data:{
                name
            }
        })
    },

(1)前端代码中的addRole方法使用了request函数发送POST请求到/manage/role/add接口,请求体中包含了name参数。

(2)后端代码中的路由/manage/role/add(添加角色接口)处理了该POST请求,并从请求体中获取name参数,然后使用RoleModel.create方法将name保存到数据库中。

3 配置Role.vue的格式化时间与添加角色方法

3.1 格式化时间

学员管理系统- 项目跟进day04 角色管理与权限设置_第1张图片

 :formatter是 Element UI 的功能。在 Element UI 的  组件中,:formatter 是一个属性,用于指定对表格数据进行格式化的函数。通过指定 :formatter 属性,你可以自定义一个函数来格式化表格中的数据。在这个例子中,resetDate 可能是一个在 Vue 组件中定义的方法,用于对日期进行重置和格式化操作。在渲染表格时,Element UI 会调用 resetDate 方法,并将当前行的数据作为参数传入,然后将返回的格式化后的数据显示在表格中。这样可以方便地在表格中显示经过格式化处理的数据。

注意:使用formateDate格式化时间功能时要引入响应组件

methods中的格式化方法:

    // 格式化日期
    resetDate(row, column, cellValue, index) {
      return formateDate(cellValue);
    },

methods中创建添加角色的方法(按钮中的功能)

    // 添加角色
    addData(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          roleApi.addRole(this.role.name).then((response) => {
            const resp = response.data;
            if (resp.status == 0) {
              this.roleFormVisible = false;
              this.fetchRoleList();
            }
          });
        } else {
          return false;
        }
      });
    },
  • this.$refs[formName].validate((valid) => {...});通过this.$refs[formName]可以获取到表单组件的引用,然后调用validate方法对表单进行验证。当验证完成后,会执行回调函数中的代码。
  • (valid) => {...}:这是一个箭头函数,接受一个参数valid,表示表单验证的结果。箭头函数内部的代码将在表单验证完成后执行。
  • if (valid) {...}如果表单验证通过,则执行条件语句中的代码
  • roleApi.addRole(this.role.name).then((response) => {...});:调用roleApi中的addRole方法,传入角色名称this.role.name作为参数,发送添加角色的请求。然后使用then方法处理请求的响应。
  • 注:roleApi是role库中的模块,可以调用模块中的方法
    // 引入
    import roleApi from "@/api/role";
  • const resp = response.data;:将响应的数据存储在变量resp中。
  • 注:通过调用roleApi.addRole(this.role.name)方法发送添加角色的请求,然后使用.then()方法来处理请求的响应。在响应的回调函数中,接收一个参数response,它包含了从服务器返回的完整的响应对象,其中包括响应的状态码、响应头部和响应体等信息。
  • if (resp.status == 0) {...}:如果响应的状态为0,表示添加角色成功,则执行条件语句中的代码。
  • this.roleFormVisible = false;:将角色表单的可见性设置为false,即隐藏角色表单。
  • this.fetchRoleList();:调用fetchRoleList方法,重新获取角色列表。
  • 注:调用this.fetchRoleList()方法,很可能是为了在成功添加角色后更新角色列表的显示。通过重新获取角色列表,可以确保在用户添加角色后,界面上能够及时更新显示最新的角色信息。
  • else { return false; }:如果表单验证未通过,则返回false。

测试: 

学员管理系统- 项目跟进day04 角色管理与权限设置_第2张图片

 代表添加角色功能成功实现,并且在前端中会有对应显示:

点击添加角色后弹出弹窗:


    
      
      
        
          
        
      
      
    

4  设置角色权限

4.1 权限弹窗设置流程

1.选中列表中某一行数据后将设置角色权限按钮取消禁用状态(判断currentRow是否为null)

(1)默认设置权限按钮是禁用状态,由于状态需要切换,故使用v-bind双向绑定

学员管理系统- 项目跟进day04 角色管理与权限设置_第3张图片

 (2)为表单中可能点击的每行内容添加

@current-change="handleCurrentChange"

 这样的话,在选中需要选择行时,其状态会发生改变,调用handleCurrentChange功能

(3)在methods中创建该方法

    handleCurrentChange(val) {
      this.currentRow = val;
    },

即行从null被切换成val(当前选中行) 并打开权限设置按钮

2.html模板中添加弹窗,弹窗中确定按钮点击事件回调函数需在methods中进行定义(updateRole)

 (1)为角色添加权限弹窗


    
      
      
      
      
    

本身 :visible.sync="roleAuthVisible"中的roleAuthVisible是false,但由于在第一步中,设置权限按钮被打开,该按钮中的click功能将roleAuthVisible设置为了true,故此处弹窗显示

注:其中的 :visible.sync="roleAuthVisible"

:visible指的是属性绑定,表示弹框的显示隐藏,当:visible的值为ture的时候,弹框显示,当为false的时候,弹框隐藏

后面的.sync是什么意思呢,指的就是同步动态双向的来表示visible的值,当我们关闭窗口的时候,这个弹框隐藏了,visible的值发生了变化,但是关闭窗口这个动作,我们没法用确定的动作去判断这个值,所以用到了vue中的双向绑定的原则,在vue中统一加上了.sync来表示同步的修改了visible的值。 

关于字符串"auth"

在这段代码中,字符串"auth"作为`ref`属性的值,用于在组件中标识一个引用。通过`this.$refs['auth']`可以获取到这个组件的实例,进而调用该实例的方法或访问其属性。在`updateRole()`方法中,通过`this.$refs['auth'].getMenus()`来获取特定组件实例的`getMenus()`方法的返回值。

3.为设置角色权限按钮添加点击事件,点击按钮弹窗展示(roleAuthVisible设置为true)参考2的(1)

4.2 为权限弹窗的上半部分"角色昵称"设置内容

学员管理系统- 项目跟进day04 角色管理与权限设置_第4张图片

 (1)首先设置第一行(上半部分):角色名称

在Auth.vue中:

学员管理系统- 项目跟进day04 角色管理与权限设置_第5张图片学员管理系统- 项目跟进day04 角色管理与权限设置_第6张图片

在这段代码中,`updateRole`是一个对象,用于存储角色信息,包括角色名称。初始值为空字符串。

`roleRules`是一个对象,用于定义表单验证规则。在此例中,`name`属性的验证规则为必填项,如果未填写会显示"请输入角色名称"的提示信息。

`mounted`是Vue实例的生命周期钩子函数,在组件挂载到页面后被调用。在这个函数内部,首先通过`props`接收到父组件传递过来的`role`信息,并用扩展运算符`...`将其值复制给`updateRole`,这样就能在本组件中使用`this.role`。(展开role中的内容--解构赋值--并将其以对象的形式传递给空字符串updateRole以存储传递过来的信息)

接着,对`authList`和`checkedKeys`进行了初始化。

`authList`是一个空数组,用于存储树形空间元素节点

`checkedKeys`是一个数组,保存了已选中的节点的key值,用于标识角色权限。

总体而言,这段代码是为了在组件渲染后,初始化角色信息和表单验证规则,并进行相关的数据处理。

(2)在父组件Role.vue中引入子组件Auth.vue

引入:

import Auth from "./Auth.vue"

 注册:

  components: {
    Auth,
  },

在权限弹窗中显示该组件:

学员管理系统- 项目跟进day04 角色管理与权限设置_第7张图片

 4.3 下半部分使用树形控件遍历显示(包含复选框)

(1)在html中添加树形组件

学员管理系统- 项目跟进day04 角色管理与权限设置_第8张图片

上述框中部分是Element UI组件库中的el-tree组件来创建一个树形结构的列表

(authList与checkedKeys是在该组件中创建的数组)

  • :data="authList":将 authList 数据绑定到树组件的 data 属性用于渲染树的节点。
  • show-checkbox:设置树节点前显示复选框,允许用户选择多个节点。
  • node-key="index"设置树节点的键值为 index,用于唯一标识每个节点。
  • :default-expanded-all="true":默认展开所有的节点。
  • :default-checked-keys="checkedKeys"使用 checkedKeys 变量作为默认选中的节点。
  • @check-change="handleCheckChange"当树节点选择状态发生改变时,触发 handleCheckChange 方法。

总的来说,这段代码是创建了一个可以展示和操作树形结构的列表,通过配置属性和事件来实现默认展开、默认选中节点以及处理节点选中状态的功能。

(2)在data()中对这两个数组作出声明

学员管理系统- 项目跟进day04 角色管理与权限设置_第9张图片

 (3)写一个方法getAuthNodes来获取预读取的列表内容

// 根据权限列表数组将元素对象中的属性替换为树形控件中的名称
    getAuthNodes(menuList){
        return menuList.map((item)=>{
            // 一级列表
            if(!item.children){
                return{
                    index:item.index,
                    label:item.title,
                };
            }else{
                // 多级列表
                return{
                    index:item.index,
                    label:item.title,
                    // 递归处理多级列表
                    children:this.getAuthNodes(item.children)
                }
            }
        })
    },

getAuthNodes(menuList) 是一个递归方法,用于将权限列表数组(menuList)转化为树形结构的节点数组。

对于每个权限项(item),如果它没有子项(!item.children)则直接将该项的index和title转化为节点对象。 如果有子项,则递归地调用getAuthNodes方法,将子项(item.children)作为参数,获取子节点数组,并将其作为当前节点的children属性的值。

(4)为树形控件添加点击回调方法:获取都选了哪些项

handleCheckChange(data, checked, indeterminate) 是一个方法,用于处理树形控件中的节点复选框状态改变时触发的事件。

// 树形控件元素点击回调
    handleCheckChange(data,checked,indeterminate){
        if(checked){
            // 如果选中项不是students并且在选中项数组中不存在,再添加到数组中,防止重复添加
            if(data.index != "/students" && this.checkedKeys.indexOf(data.index) == -1){
                this.checkedKeys.push(data.index)
            }

        }else{
            // 判断当前要删除的元素是在数组中存在的
            if(this.checkedKeys.indexOf(data.index) > 0){
                this.checkedKeys.splice(this.checkedKeys.indexOf(data.index),1)
            }
        }
        console.log("this.checkedKeys",this.checkedKeys);
    },
  • 如果选中了某个节点(checkedtrue)且该节点不是"/students",且在选中项数组this.checkedKeys中不存在该节点的键值,则将该节点的键值添加到this.checkedKeys数组中。
  • 如果取消选中某个节点(checkedfalse),则判断该节点的键值在this.checkedKeys数组中是否存在,若存在才能将该节点的键值从this.checkedKeys数组中删除。

(5)在子组件Auth.vue中设置一个方法来为父组件提供数据(都选择了哪些key) 

并传递给父组件updateRole()方法的menus属性值

 // 为父组件提供数据(选中了哪些权限---checkedKeys)
    getMenus(){
        this.updateRole.menus = this.checkedKeys
        return this.updateRole
    }

(6) 

学员管理系统- 项目跟进day04 角色管理与权限设置_第10张图片

关于字符串"auth"

在这段代码中,字符串"auth"作为`ref`属性的值,用于在组件中标识一个引用。通过`this.$refs['auth']`可以获取到这个组件的实例,进而调用该实例的方法或访问其属性。在`updateRole()`方法中,通过`this.$refs['auth'].getMenus()`来获取特定组件实例的`getMenus()`方法的返回值。

(7)在父组件Role.vue中设置更新角色权限的方法

// 点击确定更新角色权限
    updateRole(){
      const newRole = this.$refs['auth'].getMenus()
      this.currentRow.menus = newRole.menus
      this.currentRow.name = newRole.name
      this.currentRow.auth_name = memoryUtils.user.username
      roleApi.update(this.currentRow).then(response=>{
        const resp = response.data
          if(resp.status == 0 ){
            this.$message({
              type:'success',
              message:'设置角色权限成功!'
            })
          }
          this.roleAuthVisible = false
          this.fetchRoleList()
      })
    }
  • 通过获取this.$refs['auth']引用的组件调用getMenus()方法,以获取选中的菜单节点数据,将返回的结果保存在newRole变量中。
  • newRole中的menusname属性赋值给this.currentRow对象(选中的对象)的相应属性。
  • 将用户的用户名(memoryUtils.user.username)赋值给this.currentRow.auth_name属性。
  • 调用roleApi.update(this.currentRow)方法,以更新当前角色this.currentRow
  • 处理roleApi.update方法的响应结果:
    • 如果响应结果(response)中的status等于0,说明角色权限设置成功,显示一个成功的消息通知。
    • this.roleAuthVisible设为false,关闭角色权限设置窗口。
    • 调用fetchRoleList()方法,重新获取角色列表。

 (8)在子组件Auth.vue中设置mounted()

学员管理系统- 项目跟进day04 角色管理与权限设置_第11张图片

学员管理系统- 项目跟进day04 角色管理与权限设置_第12张图片

this.checkedKeys = this.role.menus 和 this.updateRole.menus = this.checkedKeys 具有不同的作用和意义:

  1. this.checkedKeys = this.role.menus

    • 这行代码的作用是将 this.role.menus 的值赋给 this.checkedKeys
    • this.role.menus 是一个属性,它的值可能是一个数组,用于表示已选中的菜单节点。
    • this.checkedKeys 是一个变量,它用于存储选中节点的键值。
  2. this.updateRole.menus = this.checkedKeys

    • 这行代码的作用是将 this.checkedKeys 的值赋给 this.updateRole.menus
    • this.updateRole 是一个对象,它是通过 this.role 进行浅拷贝创建的。
    • this.updateRole.menus 是 this.updateRole 对象的一个属性,用于存储选中的菜单节点。
    • 这行代码的目的是将选中的菜单节点更新到 this.updateRole 对象中,以便在父组件中使用。

总的来说,this.checkedKeys = this.role.menus 将 this.role.menus 的值赋给 this.checkedKeys,而 this.updateRole.menus = this.checkedKeys 将 this.checkedKeys 的值赋给 this.updateRole.menus。这样做的目的是为了在不修改原始数据的情况下,分别在不同的变量中存储菜单节点的选中状态,以供不同的功能或组件使用。

4.4 在后端路由中添加设置权限(更新数据库中用户信息)的ajax(post)请求 

(因为要将刚才设置的一系列权限内容保存到数据库中)

(1)设置角色权限

// 设置角色权限
    router.post("/manage/role/update",(req,res)=>{
        const role = req.body
        role.auth_time=Date.now()
        RoleModel.findOneAndUpdate({_id:role._id},role).then(oldRole=>{
            res.send({status:0,data:{...oldRole._doc,...role}})
        }).catch(error=>{
            console.log("添加角色异常",error);
            res.send({status:1,msg:'添加角色异常,请重试'})
        })
    })
  • 通过req.body获取请求体中的角色数据,保存在role变量中。
  • role.auth_time设置为当前时间(Date.now()),表示更新角色权限的时间。
  • 使用RoleModel模型的findOneAndUpdate方法,在数据库中查找指定_id的角色并更新。
  • 如果更新成功,将更新前的角色oldRole和更新后的角色role组合成一个新的对象,作为响应结果的data字段,同时将status设为0,表示成功。
  • 如果出现错误,将错误信息打印到控制台,并将错误信息作为响应结果的msg字段,将status设为1,表示失败。
  • 最后通过res.send()方法将响应结果返回给客户端。

(2) 在前端的src的api的role.js中设置向后端发送Post请求

  update(role){
        return request({
            url:'/manage/role/update',
            method:'post',
            data:role
        })
    }

测试:

学员管理系统- 项目跟进day04 角色管理与权限设置_第13张图片

 4.5 在前端父组件Role.vue中添加点击确定更新角色权限方法

在父组件Role.vue中设置更新角色权限的方法

// 点击确定更新角色权限
    updateRole(){
      const newRole = this.$refs['auth'].getMenus()
      this.currentRow.menus = newRole.menus
      this.currentRow.name = newRole.name
      this.currentRow.auth_name = memoryUtils.user.username
      roleApi.update(this.currentRow).then(response=>{
        const resp = response.data
          if(resp.status == 0 ){
            this.$message({
              type:'success',
              message:'设置角色权限成功!'
            })
          }
          this.roleAuthVisible = false
          this.fetchRoleList()
      })
    }
  • 通过获取this.$refs['auth']引用的组件调用getMenus()方法,以获取选中的菜单节点数据,将返回的结果保存在newRole变量中。
  • newRole中的menusname属性赋值给this.currentRow对象(选中的对象)的相应属性。
  • 将用户的用户名(memoryUtils.user.username)赋值给this.currentRow.auth_name属性。
  • 调用roleApi.update(this.currentRow)方法,以更新当前角色this.currentRow
  • 处理roleApi.update方法的响应结果:
    • 如果响应结果(response)中的status等于0,说明角色权限设置成功,显示一个成功的消息通知。
    • this.roleAuthVisible设为false,关闭角色权限设置窗口。
    • 调用fetchRoleList()方法,重新获取角色列表。

你可能感兴趣的:(javascript,前端,vue.js)