Comment Vue implémente le routage dynamique et les détails du routage dynamique

Idée de conception d'autorisation RBAC

Cible

Comprendre le modèle d'autorisation de RBAC

arrière-plan

Afin d'atteindre 不同的帐号登陆系统后能看到不同的页面,能执行不同的功能l'objectif, nous avons de nombreuses solutions, le modèle d'autorisation RBAC (Role-Based Access control), qui est une solution d'attribution d'autorisation basée sur les rôles.

Son mode d'autorisation est le suivant :

insérez la description de l'image ici

Trois points clés :

Utilisateur : la personne qui utilise le système

Point d'autorisation : combien de fonctions y a-t-il dans ce système (exemple : il y a 3 pages, chaque page a des opérations différentes)

Rôle : une collection de différents points d'autorisation

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé de sauvegarder l'image et de la télécharger directement (img-CxmEMg8V-1673401451130)(asset/image-20210427155035187.png)]

  1. Attribuer des rôles aux utilisateurs
  2. Attribuer des autorisations aux rôles

En entreprise réelle :

  1. Attribuez d'abord à l'employé un rôle spécifique

  2. Attribuez ensuite des points d'autorisation spécifiques au rôle (le bouton d'opération sous la page de salaire de la page de salaire)

    Les employés ont des points d'autorité

Rôle d'affectation d'employé - Composant de couche contextuelle

arrière-plan

À l'heure actuelle, il existe déjà certains rôles dans le système. Ensuite, nous attribuerons ces rôles à différents employés afin qu'ils puissent faire différentes choses après être entrés dans le système.

La relation entre les utilisateurs et les rôles est ** 1对多** : un utilisateur peut avoir plusieurs rôles, il devra donc préciser les permissions de ces multiples rôles. Par exemple, le président de la société peut avoir les rôles de superviseur financier et de capitaine de sécurité : le président peut lire les états financiers, et peut également contrôler le suivi.

Cible

Sur la page de gestion des employés, lorsque vous cliquez sur Attribuer un rôle , le composant s'ouvre/ferme sous la forme d'une couche contextuelle

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé d'enregistrer l'image et de la télécharger directement (img-kH47ePb8-1673401451131)(asset/permissionUse/18.png)]

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé de sauvegarder l'image et de la télécharger directement (img-aQ1JfSXk-1673401451131)(asset/permissionUse/03.png)]

train de pensée

  1. Divisez les fonctions spécifiques (les fonctions du rôle sont plus compliquées et la division des composants réduira la charge de travail)

  2. Contrôlez l'affichage via la couche contextuelle

Nouveau composant de gestion des rôles

Créez un fichier ** employees/assignRole.vue**, le contenu du modèle est le suivant

<template>
  <!-- // 分配角色 -->
  <div>
    这里将来会放置多选列表

    <div style="margin-top: 20px; text-align: right">
      <el-button type="primary">确定</el-button>
      <el-button @click="closeDialog">取消</el-button>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      roleIds: []
    }
  },
  methods: {
    closeDialog() {

    }
  }
}
</script>

Enregistrer et utiliser des composants

Dans la page d'accueil de la gestion des employés employee.vue, introduisez les composants ajoutés ci-dessus

import AssignRole from './assignRole'

components: {
  // 省略其他....
  AssignRole // 注册组件
},
  
  // 使用
<el-dialog :visiable.sync="showDialogRole">
  <assign-role/>
</el-dialog>  

Les éléments de données supplémentaires contrôlent l'affichage et le masquage de la couche contextuelle

data () {
    
    
  return {
    
    
    // 省略其它
    showDialogRole: false
  }
}

Rôles d'affectation des employés - Interactions de base

Cible

Fin de l'affichage de l'effet de la fermeture du calque contextuel

Effet d'interaction - afficher la couche contextuelle

Cliquez sur le bouton d'attribution de rôle, enregistrez l'identifiant et affichez la couche de puces.

modèle

<el-button type="text" size="small" @click="hAssignRole(scope.row)">分配角色</el-button>

le code

hEditRole({
     
     id}) {
    
    
  console.log('当前要分配角色id是', id)
  this.showRoleDialog = true
}

Effet d'interaction - fermer le calque contextuel

Les opérations suivantes entraîneront la fermeture de la popup :

  1. L'utilisateur a cliqué sur le bouton d'annulation
  2. L'utilisateur a cliqué sur le bouton OK et l'opération a réussi
  3. L'utilisateur clique sur le X dans le coin supérieur droit de la fenêtre contextuelle
<el-dialog
      title="分配角色"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :visible.sync="showDialogRole"
    >
       <assign-role @close="showDialogRole=false" />
    </el-dialog>

Sous-ensemble

<template>
  <div>
    <el-checkbox-group v-model="roleIds">
      <el-checkbox label="110">管理员</el-checkbox>
      <el-checkbox label="113">开发者</el-checkbox>
      <el-checkbox label="115">人事</el-checkbox>
    </el-checkbox-group>

    <div style="margin-top: 20px; text-align: right">
      <el-button type="primary">确定</el-button>
+      <el-button @click="closeDialog">取消</el-button>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      roleIds: []
    }
  },
  methods: {
    closeDialog() {
+      this.$emit('close')
    }
  }
}
</script>

Rôles d'affectation des employés - Obtenez une liste des rôles et affichez-les avec el-checkbox

Composant : employés/assignRole.vue

Cible

Envoyez une demande pour obtenir une liste de tous les rôles dans ce système et les afficher dans el-checkbox-group

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé d'enregistrer l'image et de la télécharger directement (img-SHM57fGx-1673401451132)(asset/07-1619407883065.png)]

train de pensée

  1. Préparez des modèles statiques et apprenez el-checkbox-group
  2. Préparer l'interface API
  3. Envoyez une demande pour obtenir les données du backend, puis affichez

Apprendre la boîte de sélection multiple el-checkbox-group

modèle

<el-checkbox-group v-model="roleIds">
  <el-checkbox label="110">管理员</el-checkbox>
  <el-checkbox label="113">开发者</el-checkbox>
  <el-checkbox label="115">人事</el-checkbox>
</el-checkbox-group>

Pour le el-checkbox-group utilisé pour représenter plusieurs choix :

  • La valeur de v-model est un tableau (indique une sélection multiple)
  • L'attribut label de son élément enfant el-checkbox détermine la valeur après avoir sélectionné cet élément

données

data () {
    
    
  return {
    
    
    roleIds: [] // 保存当前选中的权限列表
  }
}

Préparez l'API pour obtenir la liste des rôles

Le but est : obtenir tous les personnages. Cependant, le backend ne fournit pas d'interface prête à l'emploi pour obtenir directement tous les rôles.

Remarque : nous n'avons pas de liste de rôles dédiés à la fonction actuelle, nous pouvons utiliser temporairement la pageSize à 100 (équivalent à prendre la première page, 100 éléments par page) pour obtenir des données. dans le dossier src\api\setting.js,


/**
 * 获取所有角色信息
 * @param {*} params  {page, pagesize}
 * @returns
 */
export function getRoles(params) {
    
    
  return request({
    
    
    url: '/sys/role',
    method: 'GET',
    params: params
  })
}

Appelé dans le composant métier

en src\views\employees\assignRole.vue_

<script>
import {
    
     getRoles } from '@/api/setting'
export default {
    
    
  data() {
    
    
    return {
    
    
      roleIds: [],
+     list: []
    }
  },
  created() {
    
    
    this.loadRoles()
  },
  methods: {
    
    
    async loadRoles() {
    
    
      const {
    
     data } = await getRoles({
    
     page: 1, pagesize: 100 })
+     this.list = data.rows
    },
    closeDialog() {
    
    
      this.$emit('close')
    }
  }
}
</script>

Afficher les données dans le modèle

<el-checkbox-group v-model="roleIds">
  <!-- 注意:label决定当前选中的值 -->
  <el-checkbox v-for="item in list" :key="item.id" :label="item.id">
    {
   
   { item.name }}
  </el-checkbox>
</el-checkbox-group>

Remarque : l'étiquette détermine la valeur actuellement sélectionnée

résumé

Rôles d'affectation des employés - récupérer les données et remplir

Cible

​ Si l'utilisateur actuel a déjà configuré certaines données de rôle, les données de rôle configurées doivent être affichées en premier : Certaines cases sont cochées !

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé de sauvegarder l'image et de la télécharger directement (img-YLTZ10fZ-1673401451132)(asset/08-1619407893456.png)]

train de pensée

Transmettez l'identifiant de l'utilisateur dans le composant parent

Après avoir ouvert la couche contextuelle, obtenez les informations de rôle actuelles en fonction de l'ID utilisateur, puis faites écho

père en fils - père

définir l'élément de données

data() {
    
    
    return {
    
    
      // 省略其他 ...
      curEmployeId: '', // 当前的员工编号
    }
}

Lorsque vous cliquez sur attribuer un rôle, attribuez-lui une valeur

// 用户点击分配角色
hAssignRole(id) {
    
    
  this.showDialogRole = true

  this.curEmployeId = id
}

modèle

Passer les accessoires aux composants enfants

<el-dialog :visible.sync="showDialogRole" title="权限">
  <assign-role
+        :employee-id="curEmployeId"
        @close="showDialogRole=false"
      />
</el-dialog>

père en fils - fils à recevoir

<script>
 import {
      
       getUserDetailById } from '@/api/user'
 export default {
      
      
    props: {
      
      
       // 用户的id 用来查询当前用户的角色信息
        employeeId: {
      
      
      		type: String,
      		required: true
    		}
    },
  	created() {
      
      
    	this.loadRoles()
  	},

  methods: {
      
      
    async loadRoles() {
      
      
      const res = await getRoles({
      
       page: 1, pagesize: 100 })
      // 保存所有的角色
      this.list = res.data.rows
      // console.log('loadRoles...........', res)
      const info = await getUserDetailById(this.employeeId)
      console.log('getUserDetailById...........', info)
      // 保存这个员工当前的已经有的角色
      this.roleIds = info.data.roleIds
    },
 }
</script>

Problème de remplissage de rôle d'affectation d'employé : créé n'est exécuté qu'une seule fois

raison

Étant donné que le sous-composant est imbriqué dans la boîte de dialogue, il ne sera créé qu'une seule fois : créé n'est exécuté qu'une seule fois, et les opérations d'affichage et de masquage suivantes n'entraînent pas la reconstruction du composant, donc : le contenu ouvert ultérieurement est le même que la première fois .

résoudre

Solution 1 : Lorsque la couche contextuelle est masquée, détruisez le sous-composant.

<el-dialog
      title="分配角色"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :visible.sync="showDialogRole"
    >
      <assign-role
+       v-if="showDialogRole"
        :employee-id="curEmployeId"
        @close="showDialogRole=false"
      />
    </el-dialog>

Avantages : Simple ; Inconvénients : La destruction de composants pose certains problèmes de performances

Option II :

Idée : Lorsque vous cliquez pour attribuer un rôle dans le composant parent, appelez directement la méthode dans le composant enfant pour obtenir les données.

Ajouter une référence au composant enfant

<assign-role
        ref="assignRole"
        :employee-id="curEmployeId"
        @close="showDialogRole=false"
      />
// 用户点击分配角色
hAssignRole(id) {
    
    
  this.showDialogRole = true

  this.curEmployeId = id
  console.log('父组件', this.curEmployeId)
  // this.$nextTick
  // 直接找到子组件,调用方法去获取最新的数据
  this.$nextTick(() => {
    
    
    this.$refs.assignRole.loadRoles()
    // console.log('子组件中的props', this.$refs.assignRole.employeeId)
  })
}

Supprimer créé dans le prix du sous-groupe

// created() {
  //   // 组件创建时执行一次
  //   this.loadRoles()
  // },

Rôle d'affectation d'employé - Enregistrer

Cible

Enregistrer les fonctions spécifiques du rôle attribué modifié à l'utilisateur

train de pensée

Interface d'encapsulation -> interface d'appel

Attribuer une interface de rôle

Dans le api/employees.jsfichier ** **, ajoutez une méthode appelée assignRoles

/**
 * @description: 为用户分配角色
 * @param {*} data { id:当前用户id, roleIds:选中的角色id组成的数组 }
 * @return {*}
 */
export function assignRoles(data) {
    
    
  return request({
    
    
    url: '/sys/user/assignRoles',
    data,
    method: 'put'
  })
}

Confirmer la sauvegarde dans le code entreprise

Importer l'API définie ci-dessus

import {
    
     assignRoles } from '@/api/employees'

Ajouter un événement de clic au bouton

<template>
  <el-button type="primary" size="small" @click="hSave">确定</el-button>
</template>

Rappels supplémentaires enregistrés

// 保存当前角色信息
async hSubmit() {
    
    
  const res = await assignRoles({
    
     id: this.employeeId, roleIds: this.roleIds })
  console.log('保存角色', res)
  this.$emit('update-close')
}

Dans le composant parent, écoutez l'événement

<assign-role
        ref="assignRole"
        :employee-id="curEmployeId"
        @update-close="hUpdateClose"
        @close="showDialogRole=false"
      />

hMise à jourFermer :

// 用户分配角色成功
    hUpdateClose() {
    
    
      this.showDialogRole = false
      this.loadEmployeeList()
    }

Autorisations d'attribution de rôle - Description générale

Pourquoi attribuer des autorisations aux rôles

Quel est le rôle de l'utilisateur, il a certaines fonctions

Dans le code précédent, un rôle a été ajouté à l'utilisateur, donc ce que l'employé peut faire dépend des fonctions spécifiques exercées dans le rôle.

image-20210428094452560

Il existe de nombreuses fonctions de gestion des droits, qui nécessitent des composants de conditionnement.

Autorisations d'attribution de rôle - Composants de l'espace contextuel et interactions de base

Cible

Dans le module de gestion des rôles (views/settings/settings.vue), implémentez les sous-composants

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé d'enregistrer l'image et de la télécharger directement (img-0zTwqJw2-1673401451132)(asset/assign permissions.gif)]

train de pensée

Préparer le popup -> enregistrer l'événement -> fournir la méthode de données

Terminer l'attribution des points d'autorité aux rôles

Encapsuler les sous-composants

Encapsulez d'abord un composant assignPermission.vue sous les paramètres de sauvegarde.

|--settings
|---------settings.vue # 角色管理主页
|---------assignPermission.vue  #给角色分配权限

Il sera référencé et utilisé dans settings.vue.

Ajouter une couche de bombe au composant parent et introduire le composant enfant

Introduire des sous-composants dans settings.vue

import assignPermission from './assignPermission'

enregistrer

components: {
    
    
    assignPermission
  },

Ajoutez le composant el-dialog au modèle et importez-le

<!-- 分配权限的弹层 -->
<el-dialog 
    title="分配权限(一级为路由页面查看权限-二级为按钮操作权限)" :visible.sync="showDialogAssign">
  <assign-permission />
</el-dialog>

Données supplémentaires

return {
    
    
  //... 省略其它
  showDialogAssign: false, // 分配权限对话框
}

Interaction - afficher la couche contextuelle

Afficher la fenêtre contextuelle. Ajouter un événement de clic au bouton

<el-button size="small" type="success" @click="hAssign">
    分配权限
</el-button>

Définissez showDialogAssign sur true dans le rappel

methods:{
    
    
  hAssign() {
    
    
    this.showDialogAssign = true
  } 
}

Couche contextuelle de masquage d'interaction

Événement personnalisé : enfant à parent

<el-dialog
      title="分配权限(一级为路由页面查看权限-二级为按钮操作权限)"
      :visible.sync="showDialogAssign"
    >
      <assign-permission
+        @close="showDialogAssign=false"
      />
    </el-dialog>

dans le composant enfant

methods: {
    
    
    hCancel() {
    
    
    // 通过父组件去关闭弹层
      this.$emit('close')
    }
  }

Autorisations d'attribution de rôle - Obtenir des données de point d'autorisation et les afficher

Cible

Dans le composant assignPermission.vue, toutes les données des points d'autorisation du système actuel sont obtenues et affichées dans une arborescence. L'effet cible est le suivant :

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme de lien antivol, il est recommandé d'enregistrer l'image et de la télécharger directement (img-oYbV8FQO-1673401451133)(asset/image-20210428100556359.png)]

train de pensée

  1. Préparer l'interface du point d'autorisation

  2. Après l'affichage de la popup :

    1. Appelez l'API pour envoyer une requête afin d'obtenir des données ;
    2. Conversion de format de données (tableau en arbre)
    3. Liaison de modèle (afficher les données sur el-tree)

préparer l'API

Préparez l'API dans src\api\permission.js (cette API a été utilisée sur la page des points d'autorisation)

import request from '@/utils/request'

// 获取权限点列表
export function getPermissionList(params) {
    
    
  return request({
    
    
    url: '/sys/permission',
    params
  })
}

Préparer les éléments de données

permissionData: [] // 存储权限数据

Envoyer une demande pour obtenir des données

méthode d'importation

import {
    
     getPermissionList } from '@/api/permission'
import {
    
     tranListToTreeData } from '@/utils/index'

Appelé créé

created() {
  this.loadPermissionList()
},
  async loadPermissionList() {
    // 发送请求, 获取权限列表
    const { data } = await getPermissionList()
    console.log('权限列表的数据是', data)
    this.permissionData = tranListToTreeData(data)
  }

Afficher les données dans el-tree

<!-- 权限点数据展示 -->
<el-tree
    :data="permissionData"
    :props="{ label: 'name' }"
/>

Remarque : accessoires

Autorisations d'attribution de rôle - Définition des propriétés d'el-tree

Cible

Autres paramètres pour el-tree :

  1. Afficher la boîte de sélection
  2. Tout développer par défaut
  3. Fermer l'association parent-enfant
image-20210524231614693

configuration d'attribut

https://element.eleme.io/#/zh-CN/component/tree

  1. Afficher la case à cocher Afficher la case à cocher
  2. default-expand-all Développer par défaut
  3. check-strictly set true, vous pouvez fermer l'association parent-enfant
<!-- 权限点数据展示 -->
      <el-tree
        :data="permissionData"
        :props="{ label: 'name' }"
        default-expand-all
        :show-checkbox="true"
        :check-strictly="true"
      />

La méthode d'écriture par défaut-expand-all est équivalente à:default-expand-all="true"

Effet

Autorisations d'attribution de rôle - Remplissage de données

Cible

L'utilisateur actuel peut avoir certaines autorisations existantes, qui doivent être renvoyées en écho

train de pensée

  1. préparer l'API
  2. Assemblez les paramètres actuels et appelez l'api pour obtenir les données ;
  3. Afficher les données de remplissage dans l'arborescence

préparer l'API

Fichier : dans src\api\settings.js, ajoutez une méthode getRoleDetail

/**
 * @description: 获取角色详情
 * @param {*} id 角色id
 * @return {*}
 */
export function getRoleDetail(id) {
    
    
  return request({
    
    
    url: `/sys/role/${
      
      id}`
  })
}

Passer l'identifiant du parent à l'enfant

Dans le composant parent setting.vue, définissez l'élément de données :

data () {
    
    
  return {
    
    
  	// 省略其他...
  	roleId: ''
	}
}

Enregistrez le roleId lorsque vous cliquez pour attribuer des autorisations

<el-button size="mini" type="success" @click="hAssign(scope.row.id)">分配权限</el-button>

Le rappel correspondant est :

hAssign(id) {
    
    
   // 记下来id
   this.roleId = id
   this.showDialogAssign = true
},

Recevoir roleId dans la sous-classe

Dans assignPerimission.vue, les accessoires de définition supplémentaires reçoivent la valeur roleId

props: {
    
    
  roleId: {
    
    
    type: String,
    required: true
  }
}

Appelez api pour obtenir des données

Introduire l'API précédemment encapsulée

import {
    
     
  assignPerm, 
+ getRoleDetail 
} from '@/api/setting'
created() {
    
    
    // 调用接口,获取所有的权限点数据
    this.loadPermissionList()

    // 调用接口,获取当前这个角色已经具备的权限
+   this.loadPermissionByRoleId()
  },
    
async loadPermissionByRoleId() {
    
    
      // 根据roleId获取当前这个角色已经具备的权限
      const res = await getRoleDetail(this.roleId)
+      console.log('获取当前角色的已有的权限点数据', res.data.permIds)
      // 回填到树上
      this.$refs.tree.setCheckedKeys(res.data.permIds)
    },
    async loadPermissionList() {
    
    
      const res = await getPermissionList()
      console.log('获取所有的权限点数据', res)
      // 转成树状结构
      this.permissionData = tranListToTreeData(res.data)
    },

Remplir les données dans el-tree

Les données ont été obtenues, comment les remplir dans l'arbre el, pour que certaines cases à cocher soient cochées ?

答: setCheckedKeys + clé de nœud

Site officiel : https://element.eleme.io/#/zh-CN/component/tree#fang-fa

  1. Ajouter la clé de nœud d'attribut à l'arborescence
<!-- 权限点数据展示 -->
    <el-tree
      ref="refTree"
      :data="permissionData"
      :props="{ label: 'name' }"
      :default-expand-all="true"
      :show-checkbox="true"
      :check-strictly="true"
      node-key="id"
    />
  1. appeler setCheckedKeys
// 获取角色现有的权限
    async loadRoleDetail() {
      const res = await getRoleDetail(this.roleId)
      console.log('获取角色现有的权限', res.data.permIds)

      // 回填
      this.$refs.refTree.setCheckedKeys(res.data.permIds)
    },

résumé

  1. Dans le composant el-tree, renvoyez les données au composant el-tree via la méthode setCheckedKeys

Autorisations d'attribution de rôle - problème de remplissage de données : la création n'est exécutée qu'une seule fois

raison

Étant donné que le sous-composant est imbriqué dans la boîte de dialogue, il ne sera créé qu'une seule fois : créé n'est exécuté qu'une seule fois, et les opérations d'affichage et de masquage suivantes n'entraînent pas la reconstruction du composant, donc : le contenu ouvert ultérieurement est le même que la première fois .

résoudre

Solution 1 : Lorsque la couche contextuelle est masquée, détruisez le sous-composant.

<el-dialog
      title="分配角色"
      :visible.sync="showDialogRole"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
    >
      <子组件
+       v-if="showDialogAssign"
      />
    </el-dialog>

Avantages : simple, les dernières données sont obtenues ;

Inconvénients : La destruction des composants pose certains problèmes de performances,

Solution 2 : faites référence aux sous-composants via des références et appelez directement ses méthodes pour envoyer des requêtes

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé d'enregistrer l'image et de la télécharger directement (img-JrmAm932-1673401451133)(asset/image-20210428105921353.png)]

// 用户点击了权限分配
    hAssign(id) {
    
    
      // alert(id)
      // 1. 保存角色编号
      //    它会影响子组件中的props,但是,这个传递的过程是异步的
      this.roleId = id
      // 2. 弹层
      this.showDialogAssign = true
      // 3. 手动调用子组件的loadPermissionByRoleId, 去根据最新的roleId获取权限信息
      this.$nextTick(() => {
    
    
        this.$refs.permission.loadPermissionByRoleId()
      })
      }
    }

Autorisations d'attribution de rôle - Enregistrer les paramètres

Cible

Compléter la fonction d'attribution d'autorisation

train de pensée

Préparez l'api, appelez quand cliquez sur enregistrer

préparer l'API

Dans le fichier src\api\settings.js, ajoutez une API pour attribuer des autorisations

/**
 * 给角色分配权限
 * @param {*} data {id:角色id, permIds:[] 所有选中的节点的id组成的数组}
 * @returns
 */
export function assignPerm(data) {
    
    
  return request({
    
    
    url: '/sys/role/assignPrem',
    method: 'put',
    data
  })
}

Appelez l'api pour attribuer des autorisations-analyse

Appelez simplement l'API définie ci-dessus et transmettez les paramètres pertinents.

Il y a deux paramètres ici :

  1. Quel est l'ID de rôle actuel ?在点击分配权限时,可以从表格中获取, 父传子
  2. Quel est l'ID de liste d'autorisations correspondant ?通过el-tree组件的getCheckedKeys来获取用户选中的id列表

Appel api pour attribuer des autorisations - réalisation de la fonction

async hSave() {
    
    
      const permIds = this.$refs.tree.getCheckedKeys()
      // console.log('当前选中的节点数组是', permIds)
      const res = await assignPerm({
    
    
        id: this.roleId,
        permIds
      })
      console.log('保存角色的权限点的结果是', res)

      // 提示
      this.$message.success('保存角色的权限成功')
      // 关闭弹层
      this.hCancel()
    },
    hCancel() {
    
    
      // 通过父组件去关闭弹层
      this.$emit('close-dialog')

      // 清空当前的选择
      this.$refs.tree.setCheckedKeys([])
    }

Enfin, lorsque la couche pop-up est fermée, effacez les données sélectionnées par l'utilisateur dans l'arborescence

résumé

  • el-tree récupère les clés du nœud actuellement sélectionné : getCheckedKeys
  • Pour les composants el-tree, effacez la sélection actuelle : this.$refs.tree.setCheckedKeys([])

Connaître les données d'autorisation de l'utilisateur

Jusqu'à présent, nous avons implémenté tous les aspects de l'idée de conception d'autorisation RBAC. Nous avons attribué des rôles aux employés et attribué des points d'autorisation aux rôles. Les employés ont maintenant des points d'autorisation correspondants. Ensuite, nous pouvons utiliser ces points d'autorisation pour le contrôle d'autorité réel, dans le projet RH, il existe deux lieux de contrôle d'autorité :

  1. Contrôle d'autorisation du menu gauche (après que différents utilisateurs entrent dans le système, les menus qu'ils voient sont différents)
  2. Contrôle des autorisations des boutons d'opération (boutons sur la page, différentes personnes ont des autorisations différentes)

Où sont les données d'autorisation

Créez de nouvelles données d'employé dans la gestion des employés, puis utilisez le nouveau compte d'employé pour vous connecter (le mot de passe est 123456) et affichez les données renvoyées de l'interface d'informations personnelles (/api/sys/profile), comme indiqué dans la figure ci-dessous, aucune autorisation n'est configurée Le statut de retour du , vous pouvez voir que les menus et les points sous les rôles sont vides et que les employés n'ont aucune autorisation pour le moment

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé d'enregistrer l'image et de la télécharger directement (img-WN9TIr43-1673401451134)(asset/permissionUse/13.png)]

Comment modifier les données d'autorisation

Connectez-vous avec un compte administrateur, puis attribuez deux autorisations de menu et une autorisation de bouton d'opération au nouvel employé nouvellement créé, puis connectez-vous à nouveau au compte de l'employé pour afficher les informations personnelles et renvoyer les données.

Pas:

  1. Gestion des points d'autorisation > Ajouter des points d'autorisation d'opération de bouton sous la gestion des employés导入,导出

  2. Gestion des rôles > Nouveau rôle Directeur du personnel > Attribuer des autorisations aux rôles (gestion des employés, importation, exportation)

  3. Gestion des employés > Attribuer le rôle de DRH aux employés

  4. Connectez-vous à nouveau au nouveau compte d'employé, vérifiez les données d'autorisation et observez les données.rôles.menus, éléments de points

Analyse globale du menu de gauche généré dynamiquement par l'application d'autorisation

analyser

La connexion est réussie, entrez dans la garde de navigation :

  • Obtenir des informations d'autorisation personnelles
  • Générer des routes dynamiques accessibles

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé de sauvegarder l'image et de la télécharger directement (img-wMfe8si3-1673401451134)(asset/image-20210428122059657.png)]

exemple

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé d'enregistrer l'image et de la télécharger directement (img-L1oHNZ59-1673401451134)(asset/permissionUse/17.png)]

Demande d'autorisation - générer dynamiquement le menu de gauche - méthode addRoutes

Cible

Apprenez addRoutes dans l'objet vue-router et utilisez-le pour ajouter dynamiquement des configurations de routage

train de pensée

Les pages (configuration de routage) auxquelles les utilisateurs peuvent accéder doivent être dynamiques , vous devez donc au préalable maîtriser une API capable d'ajouter dynamiquement des adresses de routage

utilisation de base d'addRoutes

Format

router.addRoutes([路由配置对象])
或者:
this.$router.addRoutes([路由配置对象])

Rôle : ajouter dynamiquement une configuration de routage

exemple

// 按钮
<button @click="hAddRoute">addRoute</button>

// 回调
hAddRoute() {
	this.$router.addRoutes([{
		path: '/abc',
		component: () => import('@/views/abc'),
		}])
},

Effet

Après avoir cliqué sur le bouton, vous pouvez accéder à /abc dans l'adresse.

code de rénovation

  1. Supprimer la partie du routage dynamique dans la configuration du routage dans router/index.js

    const createRouter = () => new Router({
          
          
      // mode: 'history', // require service support
      scrollBehavior: () => ({
          
           y: 0 }),
      // routes: constantRoutes
      // 合并动态和静态的路由  , ...asyncRoutes
    - routes: [...constantRoutes, ...asyncRoutes]
    + routes: [...constantRoutes]
    })
    
  2. Introduit dans permission.js et ajouté dynamiquement à l'aide de addRoutes

Transformer la table de routage dynamique qui a été directement écrite statiquement dans le routeur sous la addRoutesforme ajoutée par appel de méthode

// 引入所有的动态路由表(未经过筛选)
+ import router, {
    
     asyncRoutes } from '@/router'

const whiteList = ['/login', '/404']
router.beforeEach(async(to, from, next) => {
    
    
  // 开启进度条
  NProgress.start()
  // 获取本地token 全局getter
  const token = store.getters.token
  if (token) {
    
    
    // 有token
    if (to.path === '/login') {
    
    
      next('/')
    } else {
    
    
      if (!store.getters.userId) {
    
    
        await store.dispatch('user/getUserInfo')
        // 改写成动态添加的方式
+       router.addRoutes(asyncRoutes)
      }
      next()
    }
  } else {
    
    
    // 没有token
    if (whiteList.includes(to.path)) {
    
    
      next()
    } else {
    
    
      next('/login')
    }
  }
  // 结束进度条
  NProgress.done()
})

Effet d'acceptation

  1. Seule la page d'accueil statique est laissée dans le menu de gauche (à résoudre plus tard)

  2. La saisie manuelle d'une certaine adresse de routage dynamique dans le navigateur est toujours disponible, ce qui prouve que nous avons effectivement ajouté le routage dynamique à notre système de routage.

Demande d'autorisation - générer dynamiquement le menu de gauche - réécrire l'emplacement de sauvegarde du menu

analyse du problème

Les données utilisées par le rendu de menu actuel (src\layout\components\Sidebar\index.vue) : this.$router.options.routesces données sont fixes et la table de routage que nous avons ajoutée via addRoutes n'existe qu'en mémoire et ne changera pasthis.$router.options.routes

Si nous voulons que les données de routage soient reflétées dans le menu immédiatement après l'appel de la méthode addRoutes, nous devons penser à une méthode supplémentaire. Pensez-y. Dans le développement de Vue, quelle technologie peut garantir que les fonctionnalités réactives peuvent également être modifiées dynamiquement ? vuex !

Cible

enregistrer les données du menu dans vuex

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme de lien antivol, il est recommandé d'enregistrer l'image et de la télécharger directement (img-4Q4i5Ywp-1673401451134)(asset/image-20210428122540218.png)]

Définir les données du menu de gestion vuex

  1. Modules supplémentaires. src/store/modulesAjoutez le module menu.js ci-dessous
    • Définir la liste des menus de données
    • Méthode pour modifier les données setMenuList
// 导入静态路由
import {
    
     constantRoutes } from '@/router'
export default {
    
    
  namespaced: true,
  state: {
    
    
    // 先以静态路由作为菜单数据的初始值
    menuList: [...constantRoutes]
  },
  mutations: {
    
    
    setMenuList(state, asyncRoutes) {
    
    
      // 将动态路由和静态路由组合起来
      state.menuList = [...constantRoutes, ...asyncRoutes]
    }
  }
}

Bien sûr, enregistrez ce module dans src/store/index.js

+ import menu from './modules/menu'

Vue.use(Vuex)

const store = new Vuex.Store({
    
    
  modules: {
    
    
    app,
    settings,
    user,
+   menu
  },
  getters
})

2. Soumettez setMenuList pour générer des données de menu complètes

Modifier le code dans src/permission.js

if (!store.getters.userId) {
    
    
        await store.dispatch('user/getUserInfo')

        // 动态添加可以访问的路由设置
        router.addRoutes(asyncRoutes)

        // 根据用户实际能访问几个页面来决定从整体8个路由设置
        // 中,过滤中出来几个,然后保存到vuex中
        store.commit('menu/setMenuList', asyncRoutes)
      }

3. La partie génération de menu est réécrite pour utiliser les données dans vuex

Dans le fichier src\layout\components\Sidebar\index.vue, modifiez

routes() {
    
    
  // 拿到的是一个完整的包含了静态路由和动态路由的数据结构
  // return this.$router.options.routes
  return this.$store.state.menu.menuList
}

résumé

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme de lien antivol, il est recommandé d'enregistrer l'image et de la télécharger directement (img-FQFaCeh7-1673401451135)(asset/image-20210525124226388.png)]

Demande d'autorisation - utiliser les données d'autorisation pour le filtrage

Cible

Dans l'étape précédente, nous avons réalisé:

  • Le routage dynamique est ajouté dynamiquement au système de routage via addRoutes
  • Enregistrer la route dynamique dans le menu de vuex

Cependant, nous n'avons pas fait correspondre les données d'autorisation. Ensuite, nous filtrons le menu dynamique à travers les données d'autorisation renvoyées par l'interface pour nous assurer que le menu complété est lié à l'autorisation de l'utilisateur.

filtrer les idées

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme de lien antivol, il est recommandé d'enregistrer l'image et de la télécharger directement (img-JQ1M2Yrk-1673401451135)(asset/image-20210525000107003.png)]

Le filtrage utilise le nom comme identifiant et vérifie si le nom de la route est cohérent avec l'indice

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé de sauvegarder l'image et de la télécharger directement (img-c8GBacDW-1673401451135)(asset/image-20210428153438963.png)]

La convention d'interface du backend est la suivante :

  • Nom de la page : ID de l'employé : employés
  • Nom de la page : ID d'autorisation : autorisations
  • Nom de la page : Identifiant de la structure organisationnelle : départements
  • Nom de la page : ID des paramètres : paramètres
  • Nom de la page : ID de salaire : salaires
  • Nom de la page : ID d'approbation : approbations
  • Nom de la page : Présences Logo : présences
  • Nom de la page : Logo de la sécurité sociale : sécurités_sociales

Renvoyer les éléments de menu des actions

Les pages auxquelles l'utilisateur peut accéder sont obtenues via des actions et n'ont qu'à revenir de l'action.

Modifier store/modules/user.jset compléter la déclaration de retour.

// 用来获取用户信息的action
    async getUserInfo(context) {
    
    
      // 1. ajax获取基本信息,包含用户id
      const rs = await getUserInfoApi()
      console.log('用来获取用户信息的,', rs)
      // 2. 根据用户id(rs.data.userId)再发请求,获取详情(包含头像)
      const info = await getUserDetailById(rs.data.userId)
      console.log('获取详情', info.data)
      // 把上边获取的两份合并在一起,保存到vuex中
      context.commit('setUserInfo', {
    
     ...info.data, ...rs.data })
+     return rs.data.roles.menus
    },

Obtenir la valeur de retour de l'action dans permission.js et filtrer

en src/permission.js_

if (!store.getters.userId) {
    
    
        // 有token,要去的不是login,就直接放行
        // 进一步获取用户信息
        // 发ajax---派发action来做
        const menus = await store.dispatch('user/getUserInfo')
        console.log('当前用户能访问的页面', menus)
        console.log('当前系统功能中提供的所有的动态路由页面是', asyncRoutes)
        // 根据本用户实际的权限menus去 asyncRoutes 中做过滤,选出本用户能访问的页面

        const filterRoutes = asyncRoutes.filter(route => {
    
    
          const routeName = route.children[0].name
          return menus.includes(routeName)
        })

        // 一定要在进入主页之前去获取用户信息

        // addRoutes用来动态添加路由配置
        // 只有在这里设置了补充了路由配置,才可能去访问页面
        // 它们不会出现左侧
        router.addRoutes(filterRoutes)

        // 把它们保存在vuex中,在src\layout\components\Sidebar\index.vue
        // 生成左侧菜单时,也应该去vuex中拿
        store.commit('menu/setMenuList', filterRoutes)
      }

Effet

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé d'enregistrer l'image et de la télécharger directement (img-EgzHy9V4-1673401451135)(asset/permissionUse/15.png)]

résumé

  • Obtenir la valeur de retour des actions
  • asyncRoutes.filter
image-20210525002110439

Corrections de bugs lors du rafraichissement de la page

question

Si nous actualisons le navigateur, nous constaterons que nous sommes passés à la page 404

Pour l'itinéraire ajouté par addRoute, l'écran sera blanc lors du rafraîchissement

raison

Désormais, la page 404 de notre configuration de routage se trouve au milieu et non à la fin de toutes les routes.

résoudre

Changez simplement la page 404 à la fin de la configuration de routage

le code

  1. path:'*'Supprimer cet élément des routes statiques dans routes/index.js

  2. Ajouté à la fin dans permission.js

// if(没有userInfo) {
    
    
if (!store.getters.userId) {
    
    
  // 有token,要去的不是login,就直接放行
  // 进一步获取用户信息
  // 发ajax---派发action来做
  const menus = await store.dispatch('user/getUserInfo')
  console.log('当前用户能访问的页面', menus)
  console.log('当前系统功能中提供的所有的动态路由页面是', asyncRoutes)
  // 根据本用户实际的权限menus去 asyncRoutes 中做过滤,选出本用户能访问的页面

  const filterRoutes = asyncRoutes.filter(route => {
    
    
    const routeName = route.children[0].name
    return menus.includes(routeName)
  })

  // 一定要在进入主页之前去获取用户信息

  // 把404加到最后一条
  filterRoutes.push( // 404 page must be placed at the end !!!
    {
    
     path: '*', redirect: '/404', hidden: true })

  // addRoutes用来动态添加路由配置
  // 只有在这里设置了补充了路由配置,才可能去访问页面
  // 它们不会出现左侧
  router.addRoutes(filterRoutes)

  // 把它们保存在vuex中,在src\layout\components\Sidebar\index.vue
  // 生成左侧菜单时,也应该去vuex中拿
  store.commit('menu/setMenuList', filterRoutes)

  // 解决刷新出现的白屏bug
  next({
    
    
    ...to, // next({ ...to })的目的,是保证路由添加完了再进入页面 (可以理解为重进一次)
    replace: true // 重进一次, 不保留重复历史
  })
} else {
    
    
  next()
}

Réinitialiser les itinéraires à la déconnexion

question

Après avoir quitté, reconnectez-vous et constatez que le menu est anormal (la console a une sortie indiquant que l'itinéraire est répété);

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé de sauvegarder l'image et de la télécharger directement (img-xfeMibRM-1673401451136)(asset/image-20210525161618731.png)]

raison

Les paramètres de routage sont router.addRoutes(filterRoutes)ajoutés via , et lorsque vous vous déconnectez, ils ne sont pas effacés, et vous vous reconnectez et les ajoutez à nouveau, il y a donc une duplication.

Il est nécessaire de réinitialiser l'autorité de routage (restaurer la valeur par défaut) et de l'ajouter à nouveau après la connexion à l'avenir, sinon, elle sera ajoutée à plusieurs reprises

résoudre

Nos router/index.jsfichiers **, ont trouvé une méthode de réinitialisation de l'itinéraire

// 重置路由
export function resetRouter() {
    
    
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // 重新设置路由的可匹配路径
}

Cette méthode consiste à ré-instancier la route, ce qui équivaut à changer une nouvelle route. La précédente ** 加的路由n'existe plus. Vous devez l'appeler lorsque vous vous déconnectez **

store/modules/user.js

import {
    
     resetRouter } from '@/router'
// 退出的action操作
logout(context) {
    
    
  // 1. 移除vuex个人信息
  context.commit('removeUserInfo')
  // 2. 移除token信息
  context.commit('removeToken')
  // 3. 重置路由
  resetRouter()
  // 4. 重置 vuex 中的路由信息 只保留每个用户都一样的静态路由数据
  //    在moudules中的一个module中去调用另一个modules中的mutation要加{root:true}
  // context.commit('setMenuList', [], { root: true })
}

Demande d'autorisation - Contrôle au niveau du bouton - Analyse

Cible

L'employé A et l'employé B peuvent accéder à la même page (prenons la gestion des employés comme exemple), mais l'employé A peut exporter Excel, mais l'employé B ne peut pas exporter Excel

train de pensée

Une fois que l'utilisateur s'est connecté avec succès, les autorisations au niveau des boutons auxquelles l'utilisateur peut accéder sont stockées dans le tableau de points. Et ces données sont stockées dans vuex, elles sont donc accessibles n'importe où dans le projet.

  • Si le logo sur un bouton apparaît à des points, il peut être affiché

Demande d'autorisation - Contrôle du niveau des boutons - Instructions personnalisées

Directives : v-pour, v-si…

Instructions définies par l'utilisateur : instructions auto-définies, car les instructions elles-mêmes ne suffisent pas, nous devons donc les définir nous-mêmes.

Utilisez-le pour le contrôle des autorisations au niveau des boutons

Examiner les directives personnalisées

formulaire d'inscription

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
    
    
  // 当被绑定的元素插入到 DOM 中时inserted会自动执行
  inserted: function(el, binding) {
    
    
    // v-focus="'abc'"  ===> binding.value = 'abc'
    console.log('focus.... binding', binding.value)
    // 聚焦元素
    el.focus()
  }
})

utiliser le format

<input v-foucs="'xxxx'" />

Résoudre la vérification des autorisations au niveau du bouton

Dans main.js, définissez la directive globale

// 注册一个全局自定义指令 `v-allow`
Vue.directive('allow', {
    
    
  inserted: function(el, binding) {
    
    
    // 从vuex中取出points,
    const points = store.state.user.userInfo.roles.points
    // 如果points有binding.value则显示
    if (points.includes(binding.value)) {
    
    
      // console.log('判断这个元素是否会显示', el, binding.value)
    } else {
    
    
      el.parentNode.removeChild(el)
      // el.style.display = 'none'
    }
  }
})

utiliser

<el-button
+           v-allow="'import_employee'"
            type="warning"
            size="small"
            @click="$router.push('/import')"
          >导入excel</el-button>

Ici le : 'import_employee'provient de l'identifiant

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé de sauvegarder l'image et de la télécharger directement (img-OHL0NZor-1673401451136)(asset/image-20210428165654008.png)]

Synthèse des points clés du processus de contrôle d'autorité

Scène d'affaires

Il existe différents départements fonctionnels dans l'entreprise, qui utilisent tous le même système, et les choses dont les personnes de différents départements ont besoin pour fonctionner dans le système sont différentes

Il est nécessaire de configurer différentes autorisations en fonction des différents rôles des employés

Idée de conception d'autorisation RBAC

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme anti-leeching, il est recommandé d'enregistrer l'image et de la télécharger directement (img-Zjgpc0W3-1673401451136)(asset/image-20210427155035187.png)]

Une idée de conception basée sur les rôles

  1. Configurer les rôles des employés (un employé peut avoir plusieurs rôles)
  2. Configurer les points d'autorisation pour les rôles (un rôle peut avoir plusieurs points d'autorisation)

Tant que les employés ont un rôle, ils ont automatiquement tous les points d'autorité liés au rôle

3. Modules métier correspondants basés sur des idées de conception d'autorité

  1. gestion des employés
  2. gestion des rôles
  3. Gestion des points d'autorisation

Les employés obtiennent des données d'autorisation

L'interface d'informations sur les employés contient toutes les données d'autorisation de l'employé actuel

userInfo:{
  roles: {
    menus: [],  // 菜单权限数据
    points: [] // 按钮权限数据
  }
}

Utiliser les données d'autorisation pour effectuer un traitement d'autorisation spécifique

  1. Contrôle des autorisations de menu

    Connexion> données d'autorisation de menu> correspondance avec toutes les données de routage dynamique locales> obtenir des données de routage dynamique filtrées en fonction des autorisations

    1. Ajouter au système de routage (le composant addRoutes peut être rendu en fonction de l'ID de chemin )
    2. Ajouté au rendu du menu de gauche (gestion vuex + v-for traversal)
  2. Contrôle des autorisations des boutons

    Connexion > Données d'autorisation du bouton > Utiliser l'ID d'autorisation séparé du bouton pour effectuer une recherche dans les données d'autorisation

    directive personnalisée

Je suppose que tu aimes

Origine blog.csdn.net/weixin_45357661/article/details/128639638
conseillé
Classement