HR-06-角色管理模块

182 阅读3分钟

角色管理模块

角色管理介绍

image.png

总结:角色的增删改查

image.png

  • 用户(员工)账号:用来登录系统
  • 角色:员工的身份,不同的身份拥有不同的菜单,角色可以分配给用户
  • 权限:功能按钮,可以分配给角色

总结:不同的用户登录系统后可以操作不同的菜单

角色管理组件布局

根据以上的结构,我们采用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>

总结:

  1. 卡片组件
  2. 选项卡组件用法
  3. 表格组件的用法

获取角色列表数据

image.png

  • 首先,封装读取角色的信息的请求 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提供的规则 注意:分页方式基于页码和每页条数

处理表格分页

image.png

需求:基于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() // 重新获取数据
}

总结:分页的本质,根据当前的页码的变化,重新加载当前页的数据,并且把之前的数据覆盖了

处理序号问题

image.png

  • 自定义序号
<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
   },
}

总结:动态计算索引的累加值

  1. 表格列组件提供的index属性绑定一个函数,用于动态计算索引
  2. 基于分页参数计算连续的索引值

添加表格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绑定表格的加载状态,接口调用之前显示加载状态,接口数据返回后隐藏状态。

删除角色功能

image.png

目标  实现删除角色的功能

  1. 绑定事件
  2. 提示删除
  3. 调用接口实现删除
  • 封装删除角色的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('删除角色失败')
    }
  })
},

总结:绑定事件;调用接口;刷新列表

  1. 作用域插槽
  2. 提示方法的使用

添加角色弹窗控制

添加角色流程

  1. 点击添加按钮,
  2. 显示弹窗
  3. 实现表单
  4. 提交表单,
  5. 刷新列表
  • 准备弹框
<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>
  • 准备数据 - 注意: 这边接口文档字段有误,namedescription
data() {
  return {
    ...
    form: {
      name: '',
      description: ''
    },
    rules: {
      name: [
        { required: true, message: '请输入角色名称', trigger: ['blur', 'change'] }
      ]
    }
  }
},

总结

  1. 表单的角色描述的名称和接口文档不一致(接口文档有误)
  2. 表单验证

添加角色提交表单

image.png

  • 封装新增角色功能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
},

总结:重置表单

  1. 直接调用表单组件的resetFields方法
  2. 也可以借助this.$options.data()方式重置表单

编辑角色封装接口

image.png

编辑角色:

  1. 点击按钮加载角色的数据并且回 填表单
  2. 修改信息后提交表单
  • 封装接口
// 修改角色
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存在与否区分两种操作)

公司信息

需求:展示公司的基本信息,调用接口;获取数据;填充表单;不允许编辑

image.png

  • 基本布局
<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>

总结:

  1. 如何获取Vuex中的状态数据
  2. 选项卡组件的用法(切换选项卡时调用接口)
  3. 调用接口;获取数据;填充表单