项目仓库:https://github.com/changeclass/vue-shop

创建子分支并推送

git checkout -b rights
git push -u origin rights

权限管理标签

根据不同等级分配不同颜色的标签。

<el-table :data="rightsList" border stripe>
    <el-table-column type="index"></el-table-column>
    <el-table-column label="权限名称" prop="authName"></el-table-column>
    <el-table-column label="路径" prop="path"></el-table-column>
    <el-table-column label="权限等级" prop="level">
        <template v-slot="scoped">
            <el-tag v-if="scoped.row.level == 0">一级</el-tag>
            <el-tag type="success" v-else-if="scoped.row.level == 1"
                    >二级</el-tag
                >
            <el-tag type="warning" v-else>三级</el-tag>
        </template>
    </el-table-column>
</el-table>

权限管理列表

将权限赋予某个角色,再将角色赋予给用户。

image-20201107102200891

权限列表使用了展开列,将el-table-columntype值改为expand即可。在展开列通过三个v-for嵌套循环三中权限。

html布局

<el-table :data="rolesList" border stripe>
    <!-- 展开列 -->
    <el-table-column type="expand">
        <template v-slot="scoped">
            <el-row
                    :class="['bdbottom', i1 === 0 ? 'bdtop' : '', 'vcenter']"
                    v-for="(item1, i1) in scoped.row.children"
                    :key="item1.id"
                    >
                <!-- 渲染一级权限 -->
                <el-col :span="4">
                    <el-tag closable @close="removeRightById(scoped.row, item1.id)">
                        {{ item1.authName }}</el-tag
                        >
                    <i class="el-icon-caret-right"></i>
                </el-col>
                <!-- 渲染二级和三级权限 -->
                <el-col :span="19">
                    <!-- 通过for循环嵌套渲染二级权限 -->
                    <el-row
                            :class="[i2 === 0 ? '' : 'bdtop', 'vcenter']"
                            v-for="(item2, i2) in item1.children"
                            :key="item2.key"
                            >
                        <!-- 二级权限 -->
                        <el-col :span="6">
                            <el-tag
                                    closable
                                    type="success"
                                    @close="removeRightById(scoped.row, item2.id)"
                                    >{{ item2.authName }}</el-tag
                                >
                            <i class="el-icon-caret-right"></i>
                        </el-col>
                        <!-- 三级权限 -->
                        <el-col :span="18">
                            <el-tag
                                    v-for="item3 in item2.children"
                                    :key="item3.id"
                                    type="warning"
                                    closable
                                    @close="removeRightById(scoped.row, item3.id)"
                                    >{{ item3.authName }}</el-tag
                                >
                        </el-col>
                    </el-row>
                </el-col>
            </el-row>
        </template>
    </el-table-column>
    <!-- 索引列 -->
    <el-table-column type="index"></el-table-column>
    <el-table-column label="角色名称" prop="roleName"></el-table-column>
    <el-table-column label="角色描述" prop="roleDesc"></el-table-column>
    <el-table-column label="操作" width="300px">
        <template>
            <el-button size="mini" type="primary" icon="el-icon-edit"
                       >编辑</el-button
                >
            <el-button size="mini" type="danger" icon="el-icon-delete"
                       >删除</el-button
                >
            <el-button size="mini" type="warning" icon="el-icon-setting"
                       >分配权限</el-button
                >
        </template>
    </el-table-column>
</el-table>

JavaScript

export default {
    data () {
        return {
            // 角色列表
            rolesList: []
        }
    },
    created () {
        // 获取所有权限
        this.getRolesList()
    },
    methods: {
        async getRolesList () {
            const { data: res } = await this.$http.get('/roles')
            if (res.meta.status !== 200) {
                return this.$message.error('获取权限列表失败')
            }
            this.rolesList = res.data
            console.log(this.rolesList)
        },
        // 移除权限
        async removeRightById (role, rightId) {
            // 弹窗提示用户
            const confirmRuselt = await this.$confirm('此操作将移除权限, 是否继续?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).catch(err => err)
            console.log(confirmRuselt)
            if (confirmRuselt !== 'confirm') {
                return this.$message.info('取消了删除!')
            }
            const { data: res } = await this.$http.delete(`roles/${role.id}/rights/${rightId}`)
            if (res.meta.status !== 200) {
                return this.$message.error('删除权限失败')
            }
            role.children = res.data
        }
    }
}

分配权限

UI实现

首先是点击按钮后弹出对话框,主要核心功能是树形组件。

<el-tree
         :data="rightsList"
         :props="treeProps"
         show-checkbox
         node-key="id"
         default-expand-all
         :default-checked-keys="defKeys"
         ></el-tree>
  • show-checkbox

    显示复选框

  • node-key

    每一个选项的key为数据中的id字段

  • :props

    用于配置显示的名以及子级属性

    data () {
       return {
         // 所有权限的数据
         rightsList: [],
         // 树形控件属性绑定对象
         treeProps: {
           label: 'authName',
           children: 'children'
         },
         // 默认选中的节点ID值
         defKeys: []
       }
     },
  • default-expand-all

    默认展开全部

  • :default-checked-keys="defKeys"

    默认勾选的项

对话框打开时应发起请求获取数据,并将权限填充到数据供html进行渲染

// 展示分配权限的对话框
async showSetRightDialog (role, arr) {
    const { data: res } = await this.$http.get('rights/tree')
    if (res.meta.status !== 200) {
        return this.$message.error('获取权限失败')
    }
    // 获取到的数据保存到data中
    this.rightsList = res.data
    // 获取权限
    this.getLeafKeys(role, this.defKeys)
    // 获取所有权限列表
    this.setRightDialogVisible = true
},
    // 通过递归的形式,获取角色下所有三级权限的ID,并保存到defKeys数组中
    getLeafKeys (node, arr) {
        // 如果当前node节点不好含children属性,则是三级节点
        if (!node.children) {
            return arr.push(node.id)
        }
        node.children.forEach(element => {
            this.getLeafKeys(element, arr)
        })
    },
        // 情况权限列表
        setRightDialogClosed () {
            this.defKeys = []
        }

修改权限

修改权限只需要将权限ID以数组形式进行传入,并将角色ID进行传入即可。

// 点击为角色分配权限
async allotRights () {
    const keys = [
        ...this.$refs.treeRef.getCheckedKeys(),
        ...this.$refs.treeRef.getHalfCheckedKeys()
    ]
    const idStr = keys.join(',')
    const { data: res } = await this.$http.post(`roles/${this.roleId}/rights`, { rids: idStr })
    console.log(res)
    if (res.meta.status !== 200) {
        return this.$message.error('更新权限失败')
    }
    this.$message.success('更新权限成功')
    this.getRolesList()
    this.setRightDialogVisible = false
}

在对话框内无法获取角色ID,因此当点击按钮时就对数据进行设置当前的角色ID。

async showSetRightDialog (role) {
    this.roleId = role.id
}

分配角色

点击分配角色后也会弹出一个对话框,对话框使用了selectoption组件。

<el-select v-model="selectedRoleId" placeholder="请选择">
    <el-option
               v-for="item in rolesList"
               :key="item.id"
               :label="item.roleName"
               :value="item.id"
               >
    </el-option>
</el-select>
  • selectedRoleId

    已经选中的ID值

// 展示分配角色的对话框
async setRole (userinfo) {
    // 将角色信息保存到数据
    this.userInfo = userinfo
    // 展示对话框前,获取角色的列表
    const { data: res } = await this.$http.get('roles')
    if (res.meta.status !== 200) {
        return this.$message.error('获取角色列表')
    }
    this.rolesList = res.data
    // 显示对话框
    this.setRoleDialogVisible = true
},
    // 点击按钮分配角色
    async saveRoleInfo () {
        if (!this.selectedRoleId) {
            return this.$message.error('请选择要分配的角色')
        }

        const { data: res } = await this.$http.put(`users/${this.userInfo.id}/role`, { rid: this.selectedRoleId })
        if (res.meta.status !== 200) {
            return this.$message.error('更新失败')
        }
        this.$message.success('更新角色列表成功')
        this.getUserList()
        this.setRoleDialogVisible = false
    },
        // 监听关闭对话框事件
        setRoleDialogClosed () {
            this.selectedRoleId = ''
            this.userinfo = ' '
        }

数据值

data(){
    // 需要被分配权限的用户信息
    userInfo: {},
    // 所有角色的数据列表
    rolesList: [],
    // 已经选中的ID值
    selectedRoleId: ''
}