角色管理模块
角色管理介绍
总结:角色的增删改查
- 用户(员工)账号:用来登录系统
- 角色:员工的身份,不同的身份拥有不同的菜单,角色可以分配给用户
- 权限:功能按钮,可以分配给角色
总结:不同的用户登录系统后可以操作不同的菜单
角色管理组件布局
根据以上的结构,我们采用element-ui的组件实现**
src/views/setting/index.vue
**
<template>
<div class="setting-container">
<div class="app-container">
<el-card>
<el-tabs>
<!-- 左侧 -->
<el-tab-pane label="角色管理">
<!-- 按钮 -->
<el-button
icon="el-icon-plus"
size="small"
type="primary"
>新增角色</el-button>
<!-- 表格 -->
<el-table>
<el-table-column label="序号" width="100" />
<el-table-column label="角色名称" width="240" />
<el-table-column label="描述" />
<el-table-column label="操作">
<el-button size="small" type="success">分配权限</el-button>
<el-button size="small" type="primary">编辑</el-button>
<el-button size="small" type="danger">删除</el-button>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="公司信息">
<!-- 公司信息 -->
</el-tab-pane>
</el-tabs>
</el-card>
</div>
</div>
</template>
总结:
- 卡片组件
- 选项卡组件用法
- 表格组件的用法
获取角色列表数据
- 首先,封装读取角色的信息的请求
src/api/setting.js
import request from '@/utils/request'
/**
* 获取角色列表
* ***/
export function reqGetRoleList(options) {
return request({
method: 'get',
url: '/sys/role',
params: options
})
}
- 然后,在页面中调用接口获取数据
src/views/setting/index.vue
import { reqGetRoleList } from '@/api/setting.js'
export default {
name: 'Setting',
data () {
return {
// 查询参数
fillterParams: {
page: 1,
pagesize: 10
},
// 角色列表
list: [],
// 角色列表的总数
total: 0
}
},
created () {
this.loadRoleList()
},
methods: {
// 加载角色列表的数据
async loadRoleList () {
try {
const ret = await reqGetRoleList(this.fillterParams)
this.list = ret.data.rows
this.total = ret.data.total
} catch {
this.$message.error('获取角色列表失败')
}
}
}
}
- 绑定表格数据
<el-table :data="list">
<el-table-column type="index" label="序号" width="120" />
<el-table-column prop="name" label="角色名称" width="240" />
<el-table-column prop="description" label="描述" />
<el-table-column label="操作">
<el-button size="small" type="success">分配权限</el-button>
<el-button size="small" type="primary">编辑</el-button>
<el-button size="small" type="danger">删除</el-button>
</el-table-column>
</el-table>
总结:调用接口;获取数据;渲染表格 注意:表格列的索引
type='index'
是ElementUI提供的规则 注意:分页方式基于页码和每页条数
处理表格分页
需求:基于ElementUI提供的分页组件实现分页
<el-pagination
layout="prev, pager, next"
:total="total"
:current-page="page"
:page-size="pagesize"
@current-change="handleCurrentChange"
/>
handleCurrentChange(index) {
this.page = index // 更新当前页
this.getRoleList() // 重新获取数据
}
总结:分页的本质,根据当前的页码的变化,重新加载当前页的数据,并且把之前的数据覆盖了
处理序号问题
- 自定义序号
<el-table-column type="index" :index="handleIndex" label="序号" width="120" />
- 配置自定义函数
methods: {
handleIndex (index) {
// 形参index表示列表数据的索引,从0开始
// 动态计算累加的索引
// (当前页码 - 1) * 每页的条数
const { page, pagesize } = this.filterParams
return (page - 1) * pagesize + 1 + index
},
}
总结:动态计算索引的累加值
- 表格列组件提供的index属性绑定一个函数,用于动态计算索引
- 基于分页参数计算连续的索引值
添加表格loading效果
- 绑定加载状态位
<el-table v-loading="loading" :data="list">
data () {
return {
loading: false
}
}
- 动态设置 loading 的状态
// 加载角色列表的数据
async loadRoleList () {
try {
this.loading = true
const ret = await reqGetRoleList(this.fillterParams)
this.list = ret.data.rows
this.total = ret.data.total
} catch {
this.$message.error('获取角色列表失败')
}
this.loading = false
}
总结:通过v-loading绑定表格的加载状态,接口调用之前显示加载状态,接口数据返回后隐藏状态。
删除角色功能
目标
实现删除角色的功能
- 绑定事件
- 提示删除
- 调用接口实现删除
- 封装删除角色的api
export function reqDeleteRole(id) {
return request({
url: `/sys/role/${id}`,
method: 'delete'
})
}
- 删除按钮注册事件
<el-table-column label="操作">
<template #default="{ row }">
<el-button size="small" type="success">分配权限</el-button>
<el-button size="small" type="primary">编辑</el-button>
<el-button size="small" type="danger" @click="delRole(row.id)">删除</el-button>
</template>
</el-table-column>
- 删除功能实现
// 删除角色
handleDelete (id) {
// 删除前进行提示
this.$confirm('确认要删除角色吗?, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
// 点击确定
const ret = await reqDeleteRole(id)
// 删除角色成功,刷新列表
if (ret.code === 10000) {
this.loadRoleList()
} else {
this.$message.error(ret.message)
}
}).catch((err) => {
if (err !== 'cancel') {
// 点击取消
this.$message.error('删除角色失败')
}
})
},
总结:绑定事件;调用接口;刷新列表
- 作用域插槽
- 提示方法的使用
添加角色弹窗控制
添加角色流程
- 点击添加按钮,
- 显示弹窗
- 实现表单
- 提交表单,
- 刷新列表
- 准备弹框
<el-dialog title="弹层标题" :visible.sync="isShowAddBox">
我是弹层
</el-dialog>
// data中添加一个状态位
showDialog: false
- 给按钮注册点击事件
<el-button
icon="el-icon-plus"
size="small"
type="primary"
@click="isShowAddBox=true"
>新增角色</el-button>
- 准备弹框表单结构
<el-dialog title="弹层标题" :visible="showDialog" @close="btnCancel">
<el-form ref="roleForm" :model="form" :rules="rules" label-width="100px">
<el-form-item label="角色名称" prop="name">
<el-input v-model="form.name" placeholder="请输入角色名称" />
</el-form-item>
<el-form-item label="角色描述">
<el-input v-model="form.description" placeholder="请输入角色描述" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="btnCancel">取消</el-button>
<el-button type="primary">确认</el-button>
</template>
</el-dialog>
- 准备数据 - 注意: 这边接口文档字段有误, 是
name
和description
data() {
return {
...
form: {
name: '',
description: ''
},
rules: {
name: [
{ required: true, message: '请输入角色名称', trigger: ['blur', 'change'] }
]
}
}
},
总结
- 表单的角色描述的名称和接口文档不一致(接口文档有误)
- 表单验证
添加角色提交表单
- 封装新增角色功能api
setting.js
export function reqAddRole(data) {
return request({
url: '/sys/role',
data,
method: 'post'
})
}
- 校验完成添加功能
<el-button type="primary" @click="handleAdd">确认</el-button>
// 添加角色提交表单
async handleAdd () {
// 添加角色,提交表单
try {
const ret = await reqAddRole(this.form)
if (ret.code === 10000) {
// 添加成功,关闭弹窗,属性列表
this.isShowAddBox = false
this.loadRoleList()
} else {
this.$message.error('添加角色失败')
}
} catch {
this.$message.error('添加角色失败')
}
},
总结:封装接口;绑定事件;验证表单;调用接口
- 重置表单的用法
- 重置表单的方法
resetFields
需要表单项有prop才可以 - 也可以通过
this.$options.data()
的方式获取表单的原始数据
- 重置表单的方法
// 取消操作
handleCancel () {
// 隐藏弹窗
this.showDialog = false
// this.$refs.roleForm.resetFields()
// this.$options.data()表示data中的原始数据
// 重置表单
this.form = this.$options.data().form
},
总结:重置表单
- 直接调用表单组件的resetFields方法
- 也可以借助this.$options.data()方式重置表单
编辑角色封装接口
编辑角色:
- 点击按钮加载角色的数据并且回 填表单
- 修改信息后提交表单
- 封装接口
// 修改角色
export function reqUpdateRole(data) {
return request({
method: 'put',
url: `/sys/role/${data.id}`,
data
})
}
// 获取角色详情
export function reqGetRoleDetail(id) {
return request({
method: 'get',
url: `/sys/role/${id}`
})
}
编辑角色显示数据
- 点击编辑按钮
<el-button size="small" type="primary" @click="handleEdit(scope.row.id)">编辑</el-button>
- 显示弹层, 获取数据回显
import { reqAddRole, reqDeleteRole, reqGetRoleDetail, reqGetRoleList } from '@/api/setting'
// 去编辑
async handleEdit (id) {
// 编辑角色:获取id,显示弹窗
this.isShowBox = true
// 调用接口获取角色的原始数据并填充表单
try {
const ret = await reqGetRoleDetail(id)
this.form = ret.data
} catch {
this.$message.error('获取角色数据失败')
}
},
- 计算属性 - 控制标题
computed: {
title() {
return this.form.id ? '编辑角色' : '添加角色'
}
},
- 编辑完成
// 添加角色提交表单
handleAdd () {
// 添加角色,提交表单
this.$refs.roleForm.validate(async valid => {
if (!valid) return
if (this.form.id) {
// 编辑操作
try {
const ret = await reqUpdateRole(this.form)
if (ret.code === 10000) {
// 编辑成功,关闭弹窗,刷新列表
this.isShowBox = false
this.loadRoleList()
} else {
this.$message.error(ret.message)
}
} catch {
this.$message.error('编辑角色失败')
}
} else {
// 添加操作
try {
const ret = await reqAddRole(this.form)
if (ret.code === 10000) {
// 添加成功,关闭弹窗,属性列表
this.isShowBox = false
this.loadRoleList()
} else {
this.$message.error('添加角色失败')
}
} catch {
this.$message.error('添加角色失败')
}
}
})
},
总结:添加和编辑角色重用提交逻辑(通过表单数据的id存在与否区分两种操作)
公司信息
需求:展示公司的基本信息,调用接口;获取数据;填充表单;不允许编辑
- 基本布局
<el-tab-pane label="公司信息">
<!-- 警告信息 -->
<el-alert
title="对公司名称、公司地址、营业执照、公司地区的更新,将使得公司资料被重新审核,请谨慎修改"
type="info"
show-icon
:closable="false"
/>
<!-- 表单 -->
<el-form label-width="120px" style="margin-top:50px">
<el-form-item label="公司名称">
<el-input disabled style="width:400px" />
</el-form-item>
<el-form-item label="公司地址">
<el-input disabled style="width:400px" />
</el-form-item>
<el-form-item label="邮箱">
<el-input disabled style="width:400px" />
</el-form-item>
<el-form-item label="备注">
<el-input type="textarea" :rows="3" disabled style="width:400px" />
</el-form-item>
</el-form>
</el-tab-pane>
- 封装接口
export function reqGetCompanyInfo(companyId) {
return request({
url: `/company/${companyId}`
})
}
- 这里需要的 companyId 在 vuex 个人信息里
computed: {
...mapState('user', ['userInfo']),
showTitle() {
return this.form.id ? '编辑角色' : '添加角色'
}
},
// 监听Tab的切换
async changeTab ({name}) {
// 参数的解构赋值
if (name === 'company') {
try {
// 获取公司的基本信息
const ret = await reqGetCompanyInfo(this.userInfo.companyId)
this.companyInfo = ret.data
if (!ret.success) {
this.$message.error(ret.message)
}
} catch {
this.$message.error('获取公司信息失败')
}
}
},
- 渲染数据
<!-- 表单 -->
<el-form label-width="120px" style="margin-top:50px">
<el-form-item label="公司名称">
<el-input v-model="companyInfo.name" disabled style="width:400px" />
</el-form-item>
<el-form-item label="公司地址">
<el-input v-model="companyInfo.companyAddress" disabled style="width:400px" />
</el-form-item>
<el-form-item label="邮箱">
<el-input v-model="companyInfo.mailbox" disabled style="width:400px" />
</el-form-item>
<el-form-item label="备注">
<el-input v-model="companyInfo.remarks" type="textarea" :rows="3" disabled style="width:400px" />
</el-form-item>
</el-form>
总结:
- 如何获取Vuex中的状态数据
- 选项卡组件的用法(切换选项卡时调用接口)
- 调用接口;获取数据;填充表单