day03
1.展示修改用户的对话框
<!--修改用户对话框-->
<el-dialog
title="修改用户"
:visible.sync="editDialogVisible"
width="50%">
<span>这是一段信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="editDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="editDialogVisible = false">确 定</el-button>
</span>
</el-dialog> <!--修改用户对话框-->
<el-dialog
title="修改用户"
:visible.sync="editDialogVisible"
width="50%">
<span>这是一段信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="editDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="editDialogVisible = false">确 定</el-button>
</span>
</el-dialog>
data中
//控制修改用户对话框的显示与隐藏
editDialogVisible: false
method中
showEditDialog() {
this.editDialogVisible = true
}
2.根据id查询对应的用户信息
首先在修改按钮上绑定单机事件,并且把scope的id值传回
<template v-slot="scope">
<!-- <template v-slot="scope">代表获取到了作用域的数据 -->
<!--修改-->
<el-button type="primary" icon="el-icon-edit" size="mini" @click="showEditDialog(scope.row.id)"></el-button>
<!--删除-->
<el-button type="danger" icon="el-icon-delete" size="mini"></el-button>
<!--分配角色-->
<el-tooltip effect="dark" content="分配角色" placement="top" :enterable="false">
<el-button type="warning" icon="el-icon-setting" size="mini"></el-button>
</el-tooltip>
</template>
根据接口文档获取id的信息,并把信息保存到editEditForm
async showEditDialog(id) {
const {data:res} = await this.$http.get('users/'+id)
//根据后台接口文档得出
if (res.meta.status !==200) return this.$message.error('查询用户信息失败!')
this.editForm = res.data
this.editDialogVisible = true
}
3.渲染修改用户的表单
<!--修改用户对话框-->
<el-dialog
title="修改用户"
:visible.sync="editDialogVisible"
width="50%">
<el-form :model="editForm" :rules="editFormRules" ref="editFormRef" label-width="70px" >
<el-form-item label="用户名" >
<el-input v-model="editForm.username" disabled></el-input>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<!-- prop是因为有校验规则-->
<el-input v-model="editForm.email" ></el-input>
</el-form-item>
<el-form-item label="手机号" prop="mobile">
<el-input v-model="editForm.mobile" ></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="editDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="editDialogVisible = false">确 定</el-button>
</span>
</el-dialog>
data中的校验规则
editFormRules: {
email:[
{required: true, message:"请输入邮箱",trigger:'blur'},
{min:6,max:15, message: '用户名长度在6~15个字符之间',trigger: 'blur'},
{validator:checkEmail,trigger: 'blur'}
],
mobile: [
{required: true, message:"请输入手机号",trigger:'blur'},
{min:6,max:15, message: '用户名长度在6~15个字符之间',trigger: 'blur'},
{validator:checkMobile,trigger: 'blur'}
]
}
4.修改用户的重置功能
添加关闭事件
<el-dialog
title="修改用户"
:visible.sync="editDialogVisible"
width="50%"
@close="editDialogClosed"
>
//监听修改用户对话框的关闭事件
editDialogClosed() {
this.$refs.editFormRef.resetFields()
}
5.完成修改用户的表单欲验证功能
确定按钮添加事件
<el-button type="primary" @click="editUserInfo">确 定</el-button>
方法
//修改用户信息并提交
editUserInfo() {
this.$refs.editFormRef.validate(valid => {
if (!valid) return
//发起修改用户信息的数据请求
})
6.修改用户的操作
看接口文档1.3.5
//修改用户信息并提交
editUserInfo() {
this.$refs.editFormRef.validate(async valid => {
if (!valid) return
//发起修改用户信息的数据请求
const {data:res} = await this.$http.put('users/'+ this.editForm.id,{email:this.editForm.email,mobile:this.editForm.mobile})
})
if (res.meta.data !== 200) return this.$message.error('更新用户失败')
//关闭对话框
this.editDialogVisible = false
//刷新数据列表
this.getUserList()
//提示修改成功
this.$message.success('更新用户成功')
}
7.删除用户操作
引入element-ui的弹框,在element.js中import MessageBox,然后
原型挂载,这样每个组件用this.$confirm都可以弹出弹框
Vue.prototype.$confirm = MessageBox.confirm
删除按钮添加removeUsersByID方法
//根据ID删除用户信息
async removeUsersByID(id) {
//询问用户是否删除用户
const confirmResult =await this.$confirm('此操作将永久删除该用户, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
).catch(err => {
return err
})
//如果用户确认删除,返回的是字符串confirm,如果用户取消删除会报错,所以需要catch捕获错误,返回结果是cancel
if (confirmResult !== 'confirm') {
return this.$message.info('已经取消了删除')
}
console.log('确认了删除')
}
8.调用API完成删除用户的操作
看接口文档1.3.6
//根据ID删除用户信息
async removeUsersByID(id) {
//询问用户是否删除用户
const confirmResult =await this.$confirm('此操作将永久删除该用户, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
).catch(err => {
return err
})
//如果用户确认删除,返回的是字符串confirm,如果用户取消删除会报错,所以需要catch捕获错误,返回结果是cancel
if (confirmResult !== 'confirm') {
return this.$message.info('已经取消了删除')
}
// console.log('确认了删除')
const {data:res} = await this.$http.delete('users/'+id)
console.log(res)
if (res.meta.status !==200) {
return this.$message.error('删除用户失败')
}
this.$message.success('删除用户成功')
this.getUserList()
}
权限列表
11.权限列表-通过路由展示权限列表
首先创建Rights组件
在router.js中引用并且添加到home的子路由中
const router = new VueRouter({
routes:[
{path:'/login',component:Login},
{path:'/home',component: Home,
redirect: '/welcome',
children : [
{path:'/welcome', component:Welcome},
{path: '/users', component: Users},
{path: '/rights',component: Rights}
]}
12.绘制面包屑导航和卡片视图
<template>
<div>
<!--面包屑-->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>权限管理</el-breadcrumb-item>
<el-breadcrumb-item>权限列表</el-breadcrumb-item>
</el-breadcrumb>
<!--卡片视图-->
<el-card>
123
</el-card>
</div>
</template>
没有div还显示不出来卡片
13.调用API获取权限列表的数据
export default {
name: "Rights",
data() {
return {
rightsList: []
}
},
created() {
this.getRightsList()
},
methods: {
//获取权限列表
async getRightsList() {
const {data:res} = await this.$http.get('rights/list')
if (res.meta.status !== 200) return this.$message.error('获取权限列表失败')
this.rightsList = res.data
console.log(this.rightsList)
}
}
}
</script>
14.权限的渲染
<el-card>
<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="scope">
<el-tag v-if="scope.row.level == '0'">一级权限</el-tag>
<el-tag type="success" v-else-if="scope.row.level == '1'">二级权限</el-tag>
<el-tag type="warning" v-else>三级权限</el-tag>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
用到了element-ui的Tag,并且用了插槽一级v-if,v-else-if,v-else来判断一级二级三级权限
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rVUfW1yK-1597247062684)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200811225717795.png)]
注意,level是字符串
15.用户-权限-角色三者之间的关系
用户分配不同的角色—角色下拥有不同的权限
角色列表
16.通过路由展示角色列表组件
创建Roles.vue组件,然后再router.js中进行引用
17.角色列表布局与获取数据
看接口1.5.1
Roles.vue
<template>
<div>
<!--面包屑-->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>权限管理</el-breadcrumb-item>
<el-breadcrumb-item>角色列表</el-breadcrumb-item>
</el-breadcrumb>
<!-- 卡片视图-->
<el-card>
<!-- 添加角色按钮区域-->
<el-row>
<el-col>
<el-button type="primary">添加用户</el-button>
</el-col>
</el-row>
<!-- 角色列表区域-->
</el-card>
</div>
</template>
<script>
export default {
name: "power",
data() {
return {
//所有角色列表数据
roleList: []
}
},
created() {
this.getRoleList()
},
methods: {
async getRoleList() {
const {data:res} = await this.$http.get('/roles')
if (res.meta.status !== 200) return this.$message.error('获取角色列表失败')
this.roleList = res.data
console.log(res)
}
}
}
</script>
<style scoped>
</style>
19.渲染角色列表数据
<template>
<div>
<!--面包屑-->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>权限管理</el-breadcrumb-item>
<el-breadcrumb-item>角色列表</el-breadcrumb-item>
</el-breadcrumb>
<!-- 卡片视图-->
<el-card>
<!-- 添加角色按钮区域-->
<el-row>
<el-col>
<el-button type="primary">添加用户</el-button>
</el-col>
</el-row>
<!-- 角色列表区域-->
<el-table :data="roleList" border stripe>
<!-- 展开列-->
<el-table-column type="expand"></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 v-slot="scope">
<el-button type="primary" icon="el-icon-edit" size="mini">编辑</el-button>
<el-button type="danger" icon="el-icon-delete" size="mini">删除</el-button>
<el-button type="warning" icon="el-icon-setting" size="mini">分配权限</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
20.角色列表-分析角色下权限渲染的实现思路
首先利用scope.row拿到对应的所有信息
然后用三层for循环显示三层权限
<!-- 展开列-->
<el-table-column type="expand">
<template v-slot="scope">
<pre>
{{scope.row}}
</pre>
</template>
</el-table-column>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vcyOqJ6W-1597247062697)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200811233927266.png)]
21.通过第一层for循环渲染一级权限
展开列中添加插槽,设置第一层for循环并且用el-tag显示
<!-- 展开列-->
<el-table-column type="expand">
<template v-slot="scope">
<el-row v-for="(item1,i1) in scope.row.children" :key="item1.id">
<!-- 渲染一级权限-->
<el-col :span="5">
<el-tag>{{item1.authName}}</el-tag>
</el-col>
<!-- 渲染二级权限-->
<el-col :span="19">
</el-col>
</el-row>
</template>
</el-table-column>
22.美化一级权限
每一个tag之间都有间隔
<style scoped>
.el-tag {
margin: 7px;
}
.bdtop {
boder-top: 1px soild #eee;
}
.bdbottm {
border-bottom: 1px solid #eee;
}
</style>
新增了灰色底线,每一个tag后面有一个小箭头
<!-- 展开列-->
<el-table-column type="expand">
<template v-slot="scope">
<el-row :class="['bdbottm',i1 === 0 ? 'bdtop' : '']" v-for="(item1,i1) in scope.row.children" :key="item1.id">
<!-- 渲染一级权限-->
<el-col :span="5">
<el-tag>{{item1.authName}}</el-tag>
<i class="el-icon-caret-right"></i>
</el-col>
<!-- 渲染二级权限-->
<el-col :span="19">
</el-col>
</el-row>
</template>
23.通过第二层for循环渲染二级权限
<!-- 渲染二级权限-->
<el-col :span="19">
<el-row>
<!-- 通过for循环 嵌套渲染二级权限-->
<el-row :class="i2 === 0 ? '': 'bdtop'" v-for="(item2,i2) in item1.children" :key="item2.id" >
<el-col>
<el-tag type="success">{{item2.authName}}</el-tag>
<i class="el-icon-caret-right"></i>
</el-col>
<el-col></el-col>
</el-row>
</el-row>
</el-col>
24.通过第三层for循环渲染三级权限
一级权限5列,剩余19个,进行了栅格化,将19划分为了24。一个row里有24个格子,二级占6列,剩下18列给三级权限
<!-- 三级权限-->
<el-col :span="18">
<el-tag v-for="(item3,i3) in item2.children" :key="item3.id" type="warning">
{{item3.authName}}
</el-tag>
</el-col>
</el-row>
</el-row>
</el-col>
25.权限数据美化
最小屏幕宽度,再assets的css的global.scc中#app中添加最小屏幕宽度min-width:1366px;以阻止屏幕太小,出现换行,很丑
#app {
height: 100%;
margin: 0;
padding: 0;
min-width: 1366px;
}
纵向居中,在Roles的style中添加
.vcenter {
display: flex;
align-items: center;
}
在需要的中添加
<el-row :class="['bdbottm',i1 === 0 ? 'bdtop' : '','vcenter']" v-for="(item1,i1) in scope.row.children"
:key="item1.id">
<el-row :class="[i2 === 0 ? '': 'bdtop','vcenter']" v-for="(item2,i2) in item1.children"
:key="item2.id" >
26.点击权限删除按钮弹出确认框
在el-tag上添加closeable即可出现删除的校查,element-ui中定义每次点击小叉都会触发close事件
method中
//根据Id删除对应权限
async removeRightById() {
//弹框是否确认删除
const confirmResult =await this.$confirm('此操作将永久删除该用户, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
).catch(err => {
return err
})
if ((confirmResult !== 'confirm')) {
return this.$message.info('取消删除')
}
console.log('确认删除')
}
27.完成删除角色还制定 权限的功能
scope是所有通过v-bind绑定的属性的集合
v-slot="scope"是父组件可以通过插槽的方式访问子组件中的data,下面的role指向的是子组件中的data
// this.getRoleList()
role.children = res.data//这样可以放置页面刷新
在removeRightById方法中传入两个参数
@close="removeRightById(scope.row,item3.id)
async removeRightById(role,rightId) {
//弹框是否确认删除
const confirmResult =await this.$confirm('此操作将永久删除该用户, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
).catch(err => {
return err
})
if ((confirmResult !== 'confirm')) {
return this.$message.info('取消删除')
}
const {data:res} = await this.$http.delete(`roles/${role.id}/rights/${rightId}`)
console.log(res)
if (res.meta.status !== 200) return this.$message.error('删除权限失败')
// this.getRoleList()
role.children = res.data
}
28.分配权限-弹出分配权限对话框并请求权限数据
添加click函数
<el-button type="warning" icon="el-icon-setting" size="mini" @click="showSetRightDialog">分配权限</el-button>
在data中,定义
setRightDialogVisible:'false'
Dialog对话框
<!-- 分配权限对话框-->
<el-dialog
title="分配权限"
:visible.sync="setRightDialogVisible"
width="50%">
<span>这是一段信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="setRightDialogVisible = false" >取 消</el-button>
<el-button type="primary" @click="setRightDialogVisible = false">确 定</el-button>
</span>
</el-dialog>
方法:
//展示分配权限对话框
async showSetRightDialog() {
this.setRightDialogVisible = true
//获取所有权限列表数据
const {data:res} = await this.$http.get('rights/tree')
// console.log(setRightDialogVisible)
if (res.meta.status !== 200) return this.$message.error('获取权限数据失败')
//把获取到的权限数据保存到data中
this.rightsList = res.data
console.log(res)
}
}
29.初步配置并使用el-tree树形组件
<!-- 树形控件 -->
<el-tree :data="rightsList" :props="treeProps"></el-tree>
//:data绑定数据源 props指定属性绑定对象
<span slot="footer" class="dialog-footer">
<el-button @click="setRightDialogVisible = false" >取 消</el-button>
<el-button type="primary" @click="setRightDialogVisible = false">确 定</el-button>
data中,定义树形组件的数据
data() {
return {
//所有角色列表数据
roleList: [],
//控制分配权限对话框的显示与隐藏
setRightDialogVisible:false,
rightsList: [],
//树形控件的树形绑定对象
treeProps: {
label:'authName',//代表我们看到的对应的是什么值
children: 'children'//父子组件通过什么节点连接
}
}
},
30.优化树形空间的展示效果
element-ui定义了只要添加了show-checkbox就可以添加复选框
node-key是每个树节点用来作为唯一标识的树形,整棵树应该是唯一的,类型是String,代表只要选中了复选框就选中了相应的ID值
default-expand-all为true的时候默认打开所有标签
<el-tree :data="rightsList" :props="treeProps" show-checkbox></el-tree>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5g0CCvxD-1597247062703)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200812192308979.png)]
31.分配权限-分析已有权限默认勾选的实现思路
<!-- 树形控件 -->
<el-tree :data="rightsList" :props="treeProps" show-checkbox
node-key="id" default-expand-all :default-checked-keys="defKeys"></el-tree>
default-checked-keys默认勾选节点的key数组,在data中定义defKeys
//默认选中的节点Id值数组
defKeys:[105,106]
32.已有权限就默认勾选
定义获取三级权限的函数
//通过递归的形式,获取角色所有三级权限的id,并保存到defKeys数组中
getLeafKeys(node,arr){
//如果当前node节点不包含children属性,则是三级节点
if(!node.children){
return arr.push(node.id)
}
node.children.forEach(item =>
this.getLeafKeys(item,arr))
}
在show中调用getLeafKeys,showSetRaightDialog中传入参数
async showSetRightDialog(role,arr) {
//递归获取三级节点的id
this.getLeafKeys(role,this.defKeys)
this.setRightDialogVisible = true
//获取所有权限列表数据
const {data:res} = await this.$http.get('rights/tree')
// console.log(setRightDialogVisible)
if (res.meta.status !== 200) return this.$message.error('获取权限数据失败')
//把获取到的权限数据保存到data中
this.rightsList = res.data
console.log(res)
},
最后在分配权限的地方调用函数
<el-button type="warning" icon="el-icon-setting" size="mini"
@click="showSetRightDialog(scope.row,defKeys)">分配权限</el-button>
33.在关闭对话框时重置defKeys
<el-button type="warning" icon="el-icon-setting" size="mini"
@click="showSetRightDialog(scope.row,defKeys)" @close="setRightDialogClosed">分配权限</el-button>
//监听分配权限对话框的关闭事件
setRightDialogClosed() {
this.defKeys = []
}
33.调用API完成分配权限的功能
看1.5.3
要获取被勾选的复选框的id值,使用element-ui的getCheckedKeys获取已经勾选的0数组和getHalfCheckedKeys获取半选中的返回一个数组
确定按钮添加allotRights点击事件
<!-- 树形控件 -->
<el-tree :data="rightsList" :props="treeProps" show-checkbox
node-key="id" default-expand-all :default-checked-keys="defKeys" ref="treeRef"></el-tree>
<span slot="footer" class="dialog-footer">
<el-button @click="setRightDialogVisible = false" >取 消</el-button>
<el-button type="primary" @click="allotRights">确 定</el-button>
</span>
数据data中
export default {
name: "power",
data() {
return {
//所有角色列表数据
roleList: [],
//控制分配权限对话框的显示与隐藏
setRightDialogVisible:false,
rightsList: [],
//树形控件的树形绑定对象
treeProps: {
label:'authName',
children: 'children'
},
//默认选中的节点Id值数组
defKeys:[],
//当前即将分配权限的角色ID
roleId: ''
}
//点击为角色分配权限
async allotRights() {
const key = [
...this.$refs.treeRef.getCheckedKeys(),
...this.$refs.treeRef.getHalfCheckedKeys()
]
const ifStr = key.join(',')
const {data:res} = await this.$http.post(`roles/${this.roleId}/rights`,{rids:ifStr})
if (res.meta.status !== 200) return this.$message.error('分配权限失败')
this.$message.success('分配权限成功')
this.getRoleList()
this.setRightDialogVisible = false
}
35.渲染分配角色的对话框并请求角色列表数据
在User.vue中为分配角色设置
在data中
//所有角色的数据列表
rolesList:[],
//需要被分配角色的用户信息
userInfo:'',
//控制分配角色对话框的显示与隐藏
setRoleDialogVisible: false,
方法
//展示分配角色的对话框
async setRole(userInfo) {
this.userInfo = userInfo
this.setRoleDialogVisible = true
//在展示对话框之前,获取所有角色的列表
const {data:res} = await this.$http.get('roles')
if (res.meta.status !== 200) return this.$message.error('获取角色列表失败')
this.rolesList = res.data
}
在标签中绑定事件
<!--分配角色-->
<el-tooltip effect="dark" content="分配角色" placement="top" :enterable="false">
<el-button type="warning" icon="el-icon-setting" size="mini" @click="setRole(scope.row)"></el-button>
</el-tooltip>
分配角色对话框设置
<!-- 分配角色的对话框-->
<el-dialog
title="分配角色"
:visible.sync="setRoleDialogVisible"
width="50%">
<div>
<p>当前的用户: {{userInfo.username}}</p>
<p>当前的角色:{{userInfo.role_name}}</p>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="setRoleDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="setRoleDialogVisible = false">确 定</el-button>
</span>
</el-dialog>
36.分配角色渲染角色列表的select下拉菜单
用element-ui的select选择器
data中添加selectedRoleId:’’,
<el-dialog
title="分配角色"
:visible.sync="setRoleDialogVisible"
width="50%">
<div>
<p>当前的用户: {{userInfo.username}}</p>
<p>当前的角色:{{userInfo.role_name}}</p>
<p>分配新角色:
<el-select v-model="selectedRoleId" placeholder="请选择">
<el-option
v-for="(item,id) in rolesList"
:key="item.value"
:label="item.roleName"//我们看到的文字
:value="item.id">
</el-option>
</el-select>
</p>
</div>
37.分配角色功能
绑定事件
<el-button type="primary" @click="saveRoleInfo">确 定</el-button>
方法
//点击按钮,分配橘色
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.getUserList()
this.setRoleDialogVisible = false
}