拉钩教育管理系统项目实战(四)- 角色管理、用户管理

351 阅读4分钟

笔记来源:拉勾教育 - 大前端就业集训营

文章内容:学习过程中的笔记、感悟、和经验

角色管理

基础布局、数据展示、列表展示、删除功能和以前一样,可以课下联系练习

角色管理分析和准备工作

和资源管理一样,新建子组件,把结构书写在子组件中

结构上面为表单,下面为列表和添加按钮

如果双标签里面没有内容,那么可以直接写成< />

使用按条件查询接口,这样可以把筛选功能也一起处理

删除角色使用删除角色接口

设置加载中处理

时间处理

src/views/role/index.vue

<template>
<!-- 创建子组件 -->
  <Content/>
</template>

<script>
// 引入子组件
import Content from './son/content.vue'
export default {
  name: 'role',
  // 注册子组件
  components: {
    Content
  }
}
</script>

src/views/role/son/content.vue

<template>
<!-- 外层容器 -->
  <el-card class="box-card">
    <!-- 头部 -->
    <div slot="header" class="clearfix">
      <!-- 表单 -->
      <el-form :inline="true" :model="formInline" class="demo-form-inline">
        <el-form-item label="角色名称">
          <el-input v-model="formInline.user" placeholder="角色名称"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary">查询</el-button>
        </el-form-item>
        <el-form-item>
          <el-button>重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 表格 -->
    <el-table
      :data="tableData"
      style="width: 100%">
      <el-table-column
        prop="id"
        label="编号">
      </el-table-column>
      <el-table-column
        prop="name"
        label="角色名称">
      </el-table-column>
      <el-table-column
        prop="description"
        label="描述">
      </el-table-column>
      <el-table-column
        label="添加时间">
        <template slot-scope="scope">
          <!-- 使用过滤器过滤插槽数据 -->
          <span>{{scope.row.createdTime | time}}</span>
        </template>
      </el-table-column>
      <el-table-column
        prop="address"
        label="操作"
        width="180">
        <template slot-scope="scope">
          <!-- 编辑按钮 -->
          <el-button
            size="mini"
            @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
            <!-- 删除按钮,添加事件 -->
          <el-button
            size="mini"
            type="danger"
            @click="roleDelete(scope.row.id)">删除</el-button>
      </template>
      </el-table-column>
    </el-table>
  </el-card>
</template>

<script>
// 引入按条件查询角色、删除角色
import { getRolePages, deleteRole } from '@/services/role'
export default {
  data () {
    return {
      formInline: {
      },
      // 表格数据
      tableData: []
    }
  },
  // 生命周期钩子函数
  created () {
    // 获取数据,使用控对象作为参数
    this.getRole({})
  },
  // 方法
  methods: {
    // 获取角色
    async getRole (obj) {
      const { data } = await getRolePages(obj)
      if (data.code === '000000') {
        // 获取成功将数据交给表格进行渲染
        this.tableData = data.data.records
      }
    },
    // 删除角色
    async roleDelete (id) {
      const { data } = await deleteRole(id)
      if (data.code === '000000') {
        // 如果删除成功,弹出提示消息,并且重新渲染
        this.$message({
          message: '删除成功',
          type: 'success'
        })
        this.getRole({})
      }
    }
  },
  // 过滤器
  filters: {
    // 时间格式过滤器
    time (data) {
      data = new Date()
      return `${data.getFullYear()}/${data.getMonth()}/${data.getDay()} ${data.getHours()}:${data.getMinutes()}:${data.getSeconds()}`
    }
  }
}
</script>

// src/services/role.js

// 引入接口模块
import request from '@/utils/request'

// 按条件查询角色
export const getRolePages = data => {
  return request({
    method: 'post',
    url: '/boss/role/getRolePages',
    data
  })
}

// 删除角色
export const deleteRole = id => {
  return request({
    method: 'delete',
    url: `/boss/role/${id}`
  })
}

添加角色布局

点击添加按钮弹出对话框组件,在内部设置功能

对话框内部创建一个新组件,把功能模块写在新组件中,当然添加和编辑是一样的结构,可以共用一个组件

src/views/role/son/content.vue

<template>
<!-- 外层容器 -->
  <el-card class="box-card">
    <!-- 头部 -->
    <div slot="header" class="clearfix">
      <!-- 表单 -->
      <el-form :inline="true" :model="formInline" class="demo-form-inline">
        <el-form-item label="角色名称">
          <el-input v-model="formInline.user" placeholder="角色名称"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary">查询</el-button>
        </el-form-item>
        <el-form-item>
          <el-button>重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 添加角色按钮,添加点击事件 -->
    <el-button @click="addRole">添加角色</el-button>
    <!-- 表格 -->
    <el-table
      :data="tableData"
      style="width: 100%">
      <el-table-column
        prop="id"
        label="编号">
      </el-table-column>
      <el-table-column
        prop="name"
        label="角色名称">
      </el-table-column>
      <el-table-column
        prop="description"
        label="描述">
      </el-table-column>
      <el-table-column
        label="添加时间">
        <template slot-scope="scope">
          <!-- 使用过滤器过滤插槽数据 -->
          <span>{{scope.row.createdTime | time}}</span>
        </template>
      </el-table-column>
      <el-table-column
        prop="address"
        label="操作"
        width="180">
        <template slot-scope="scope">
          <!-- 编辑按钮 -->
          <el-button
            size="mini"
            @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
            <!-- 删除按钮,添加事件 -->
          <el-button
            size="mini"
            type="danger"
            @click="roleDelete(scope.row.id)">删除</el-button>
      </template>
      </el-table-column>
    </el-table>
    <!-- 创建子组件实例,传递参数show,设置自定义事件 -->
    <Dialog :show="centerDialogVisible" @unShow="unShow"/>
  </el-card>
</template>

<script>
// 引入按条件查询角色、删除角色
import { getRolePages, deleteRole } from '@/services/role'
// 引入组件
import Dialog from './dialog'
export default {
  data () {
    return {
      formInline: {
      },
      // 表格数据
      tableData: [],
      // 对话框信号值,ture显示,false隐藏
      centerDialogVisible: false
    }
  },
  // 生命周期钩子函数
  created () {
    // 获取数据,使用控对象作为参数
    this.getRole({})
  },
  // 方法
  methods: {
    // 修改信号值隐藏对话框
    unShow () {
      this.centerDialogVisible = false
    },
    // 添加角色按钮事件
    addRole () {
      this.centerDialogVisible = true
    },
    // 获取角色
    async getRole (obj) {
      const { data } = await getRolePages(obj)
      if (data.code === '000000') {
        // 获取成功将数据交给表格进行渲染
        this.tableData = data.data.records
      }
    },
    // 删除角色
    async roleDelete (id) {
      const { data } = await deleteRole(id)
      if (data.code === '000000') {
        // 如果删除成功,弹出提示消息,并且重新渲染
        this.$message({
          message: '删除成功',
          type: 'success'
        })
        this.getRole({})
      }
    }
  },
  // 过滤器
  filters: {
    // 时间格式过滤器
    time (data) {
      data = new Date()
      return `${data.getFullYear()}/${data.getMonth()}/${data.getDay()} ${data.getHours()}:${data.getMinutes()}:${data.getSeconds()}`
    }
  },
  // 注册组件
  components: {
    Dialog
  }
}
</script>

src/views/role/son/dialog.vue - 新建子组件

<template>
<!-- 对话框,绑定show -->
  <el-dialog
    title="提示"
    :visible.sync="show"
    width="30%"
    center
  >
    <el-form :model="formLabelAlign">
      <el-form-item label="角色名称">
        <el-input v-model="formLabelAlign.name"></el-input>
      </el-form-item>
      <el-form-item label="角色编码">
        <el-input v-model="formLabelAlign.code"></el-input>
      </el-form-item>
      <el-form-item label="角色描述">
        <el-input v-model="formLabelAlign.description"></el-input>
      </el-form-item>
    </el-form>
    <span slot="footer" class="dialog-footer">
      <!-- 确定和取消按钮绑定事件 -->
      <el-button @click="cancel">取 消</el-button>
      <el-button type="primary" @click="confirm"
        >确 定</el-button
      >
    </span>
  </el-dialog>
</template>

<script>
export default {
  // 父组件传递的参数
  props: ['show'],
  data () {
    return {
      // 对话框内部组件数据
      formLabelAlign: {}
    }
  },
  methods: {
    // 确定按钮点击事件函数
    confirm () {
      this.$emit('unShow')
      console.log('确定')
    },
    // 取消按钮点击事件函数
    cancel () {
      // 触发子组件自定义事件
      this.$emit('unShow')
      console.log('取消')
    }
  }
}
</script>

添加角色功能实现

使用保存或更新角色接口

添加角色之后要关闭提示框,需要使用子向父通信

清空表单,直接设置空空即可

确认后刷新列表

取消按钮直接关闭,但是不更新数据,清空表单内容

// src/services/role.js

// 更新或保存角色
export const saveOrUpdate = data => {
  return request({
    method: 'post',
    url: '/boss/role/saveOrUpdate',
    data
  })
}
src/views/role/son/content.vue

<template>
<!-- 外层容器 -->
  <el-card class="box-card">
    <!-- 头部 -->
    <div slot="header" class="clearfix">
      <!-- 表单 -->
      <el-form :inline="true" :model="formInline" class="demo-form-inline">
        <el-form-item label="角色名称">
          <el-input v-model="formInline.user" placeholder="角色名称"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary">查询</el-button>
        </el-form-item>
        <el-form-item>
          <el-button>重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 添加角色按钮,添加点击事件 -->
    <el-button @click="addRole">添加角色</el-button>
    <!-- 表格 -->
    <el-table
      :data="tableData"
      style="width: 100%">
      <el-table-column
        prop="id"
        label="编号">
      </el-table-column>
      <el-table-column
        prop="name"
        label="角色名称">
      </el-table-column>
      <el-table-column
        prop="description"
        label="描述">
      </el-table-column>
      <el-table-column
        label="添加时间">
        <template slot-scope="scope">
          <!-- 使用过滤器过滤插槽数据 -->
          <span>{{scope.row.createdTime | time}}</span>
        </template>
      </el-table-column>
      <el-table-column
        prop="address"
        label="操作"
        width="180">
        <template slot-scope="scope">
          <!-- 编辑按钮 -->
          <el-button
            size="mini"
            @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
            <!-- 删除按钮,添加事件 -->
          <el-button
            size="mini"
            type="danger"
            @click="roleDelete(scope.row.id)">删除</el-button>
      </template>
      </el-table-column>
    </el-table>
    <!-- 创建子组件实例,传递参数show,设置自定义事件 -->
    <Dialog :show="centerDialogVisible" @unShow="unShow" @upDate="getRole"/>
  </el-card>
</template>

<script>
// 引入按条件查询角色、删除角色
import { getRolePages, deleteRole } from '@/services/role'
// 引入组件
import Dialog from './dialog'
export default {
  data () {
    return {
      formInline: {
      },
      // 表格数据
      tableData: [],
      // 对话框信号值,ture显示,false隐藏
      centerDialogVisible: false
    }
  },
  // 生命周期钩子函数
  created () {
    // 获取数据,使用控对象作为参数
    this.getRole({})
  },
  // 方法
  methods: {
    // 修改信号值隐藏对话框
    unShow () {
      this.centerDialogVisible = false
    },
    // 添加角色按钮事件
    addRole () {
      this.centerDialogVisible = true
    },
    // 获取角色
    async getRole (obj) {
      const { data } = await getRolePages(obj)
      if (data.code === '000000') {
        // 获取成功将数据交给表格进行渲染
        this.tableData = data.data.records
      }
    },
    // 删除角色
    async roleDelete (id) {
      const { data } = await deleteRole(id)
      if (data.code === '000000') {
        // 如果删除成功,弹出提示消息,并且重新渲染
        this.$message({
          message: '删除成功',
          type: 'success'
        })
        this.getRole({})
      }
    }
  },
  // 过滤器
  filters: {
    // 时间格式过滤器
    time (data) {
      data = new Date()
      return `${data.getFullYear()}/${data.getMonth()}/${data.getDay()} ${data.getHours()}:${data.getMinutes()}:${data.getSeconds()}`
    }
  },
  // 注册组件
  components: {
    Dialog
  }
}
</script>

src/views/role/son/dialog.vue

<template>
<!-- 对话框,绑定show -->
  <el-dialog
    title="提示"
    :visible.sync="show"
    width="30%"
    center
  >
    <el-form :model="formLabelAlign">
      <el-form-item label="角色名称">
        <el-input v-model="formLabelAlign.name"></el-input>
      </el-form-item>
      <el-form-item label="角色编码">
        <el-input v-model="formLabelAlign.code"></el-input>
      </el-form-item>
      <el-form-item label="角色描述">
        <el-input v-model="formLabelAlign.description"></el-input>
      </el-form-item>
    </el-form>
    <span slot="footer" class="dialog-footer">
      <!-- 确定和取消按钮绑定事件 -->
      <el-button @click="cancel">取 消</el-button>
      <el-button type="primary" @click="confirm"
        >确 定</el-button
      >
    </span>
  </el-dialog>
</template>

<script>
// 引入更新或保存角色
import { saveOrUpdate } from '@/services/role'
export default {
  // 父组件传递的参数
  props: ['show'],
  data () {
    return {
      // 对话框内部组件数据
      formLabelAlign: {}
    }
  },
  methods: {
    // 确定按钮点击事件函数
    async confirm () {
      // 判断必填项是否为空
      if (this.formLabelAlign.name && this.formLabelAlign.code) {
        // 如果必填项不为空获取数据
        const { data } = await saveOrUpdate(this.formLabelAlign)
        if (data.code === '000000') {
          // 如果添加或者保存成功弹出提示
          this.$message({
            message: '保存角色成功',
            type: 'success'
          })
          // 触发自定义事件,清空数据
          this.$emit('unShow')
          this.formLabelAlign = {}
          this.$emit('upDate')
        }
      } else {
        // 提示必填项必填
        this.$message.error('角色名称和编码是必填项哦')
      }
    },
    // 取消按钮点击事件函数
    cancel () {
      // 触发子组件自定义事件
      this.$emit('unShow')
      // 清空数据
      this.formLabelAlign = {}
    }
  }
}
</script>

编辑角色

编辑角色和添加角色使用同一个对话框,所以我们需要创建一个信号量标记当前是编辑还是添加,子组件接收数据判断是否需要拉去编辑的数据(我认为可以直接判断是否有传入参数,如果传入了参数就代表编辑)

使用获取角色接口

// src/services/role.js

// 引入接口模块
import request from '@/utils/request'

// 按条件查询角色
export const getRolePages = (data = {}) => {
  return request({
    method: 'post',
    url: '/boss/role/getRolePages',
    data
  })
}

// 删除角色
export const deleteRole = id => {
  return request({
    method: 'delete',
    url: `/boss/role/${id}`
  })
}

// 更新或保存角色
export const saveOrUpdate = data => {
  return request({
    method: 'post',
    url: '/boss/role/saveOrUpdate',
    data
  })
}

// 获取角色信息
export const getRole = id => {
  return request({
    method: 'get',
    url: `/boss/role/${id}`
  })
}

src/views/role/son/content.vue

<template>
<!-- 外层容器 -->
  <el-card class="box-card">
    <!-- 头部 -->
    <div slot="header" class="clearfix">
      <!-- 表单 -->
      <el-form :inline="true" :model="formInline" class="demo-form-inline">
        <el-form-item label="角色名称">
          <el-input v-model="formInline.user" placeholder="角色名称"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary">查询</el-button>
        </el-form-item>
        <el-form-item>
          <el-button>重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 添加角色按钮,添加点击事件 -->
    <el-button @click="addRole">添加角色</el-button>
    <!-- 表格 -->
    <el-table
      :data="tableData"
      style="width: 100%">
      <el-table-column
        prop="id"
        label="编号">
      </el-table-column>
      <el-table-column
        prop="name"
        label="角色名称">
      </el-table-column>
      <el-table-column
        prop="description"
        label="描述">
      </el-table-column>
      <el-table-column
        label="添加时间">
        <template slot-scope="scope">
          <!-- 使用过滤器过滤插槽数据 -->
          <span>{{scope.row.createdTime | time}}</span>
        </template>
      </el-table-column>
      <el-table-column
        prop="address"
        label="操作"
        width="180">
        <template slot-scope="scope">
          <!-- 编辑按钮 -->
          <el-button
            size="mini"
            @click="handleEdit(scope.row.id)">编辑</el-button>
            <!-- 删除按钮,添加事件 -->
          <el-button
            size="mini"
            type="danger"
            @click="roleDelete(scope.row.id)">删除</el-button>
      </template>
      </el-table-column>
    </el-table>
    <!-- 创建子组件实例,传递参数show,设置自定义事件 -->
    <Dialog :show="centerDialogVisible" :getId="getId" @reset="reset" @upDate="getRole"/>
  </el-card>
</template>

<script>
// 引入按条件查询角色、删除角色
import { getRolePages, deleteRole } from '@/services/role'
// 引入组件
import Dialog from './dialog'
export default {
  data () {
    return {
      formInline: {
      },
      // 表格数据
      tableData: [],
      // 对话框信号值,ture显示,false隐藏
      centerDialogVisible: false,
      // 信号值:当前需要编辑的角色id,默认为0
      getId: 0
    }
  },
  // 生命周期钩子函数
  created () {
    // 获取数据,使用控对象作为参数
    this.getRole({})
  },
  // 方法
  methods: {
    // 编辑按钮事件
    handleEdit (id) {
      // 修改信号值
      this.getId = id
      this.centerDialogVisible = true
    },
    // 组件自定义事件函数,重置信号值
    reset () {
      this.centerDialogVisible = false
      this.getId = 0
    },
    // 添加角色按钮事件
    addRole () {
      this.centerDialogVisible = true
    },
    // 获取角色
    async getRole (obj) {
      const { data } = await getRolePages(obj)
      if (data.code === '000000') {
        // 获取成功将数据交给表格进行渲染
        this.tableData = data.data.records
      }
    },
    // 删除角色
    async roleDelete (id) {
      const { data } = await deleteRole(id)
      if (data.code === '000000') {
        // 如果删除成功,弹出提示消息,并且重新渲染
        this.$message({
          message: '删除成功',
          type: 'success'
        })
        this.getRole()
      }
    }
  },
  // 过滤器
  filters: {
    // 时间格式过滤器
    time (data) {
      data = new Date()
      return `${data.getFullYear()}/${data.getMonth()}/${data.getDay()} ${data.getHours()}:${data.getMinutes()}:${data.getSeconds()}`
    }
  },
  // 注册组件
  components: {
    Dialog
  }
}
</script>

src/views/role/son/dialog.vue

<template>
<!-- 对话框,绑定show,禁止关闭按钮和点击消失 -->
  <el-dialog
    title="角色"
    :visible.sync="show"
    width="30%"
    center
    :show-close="false"
    :close-on-click-modal="false"
  >
    <el-form :model="formLabelAlign">
      <el-form-item label="角色名称">
        <el-input v-model="formLabelAlign.name"></el-input>
      </el-form-item>
      <el-form-item label="角色编码">
        <el-input v-model="formLabelAlign.code"></el-input>
      </el-form-item>
      <el-form-item label="角色描述">
        <el-input v-model="formLabelAlign.description"></el-input>
      </el-form-item>
    </el-form>
    <span slot="footer" class="dialog-footer">
      <!-- 确定和取消按钮绑定事件 -->
      <el-button @click="cancel">取 消</el-button>
      <el-button type="primary" @click="confirm"
        >确 定</el-button
      >
    </span>
  </el-dialog>
</template>

<script>
// 引入更新或保存角色
import { saveOrUpdate, getRole } from '@/services/role'
export default {
  // 父组件传递的参数
  props: ['show', 'getId'],
  data () {
    return {
      // 对话框内部组件数据
      formLabelAlign: {}
    }
  },
  methods: {
    // 获取需要编辑的角色数据
    async getInfo (id) {
      if (id !== 0) {
        // 如果传入的角色id不是0,获取角色数据,否则不获取数据
        const { data } = await getRole(id)
        if (data.code === '000000') {
          this.formLabelAlign = data.data
        }
      }
    },
    // 确定按钮点击事件函数
    async confirm () {
      // 判断必填项是否为空
      if (this.formLabelAlign.name && this.formLabelAlign.code) {
        // 如果必填项不为空获取数据
        const { data } = await saveOrUpdate(this.formLabelAlign)
        if (data.code === '000000') {
          // 如果添加或者保存成功弹出提示
          this.$message({
            message: '保存角色成功',
            type: 'success'
          })
          // 触发自定义事件,清空数据
          this.$emit('reset')
          this.formLabelAlign = {}
          this.$emit('upDate')
        }
      } else {
        // 提示必填项必填
        this.$message.error('角色名称和编码是必填项哦')
      }
    },
    // 取消按钮点击事件函数
    cancel () {
      // 触发子组件自定义事件
      this.$emit('reset')
      // 清空数据
      this.formLabelAlign = {}
    }
  },
  // 侦听器
  watch: {
    // 侦听show,一旦show为true,立马调用函数
    show (newvalue) {
      if (newvalue) {
        this.getInfo(this.getId)
      }
    }
  }
}
</script>

分配菜单布局

分配菜单功能使用独立页面,所以在角色管理下同级别创建页面

路由添加新路由

点击分配菜单跳转到页面,带参数跳转

这里按照平常的方法就不适合作为组件使用,所以使用路径路由传参的方式进行参数传递(路由中设置props:true,组件使用props获取)设置参数必须(required:true)

// src/router/index.js

{
    // 分配菜单
    name: 'AssignmentMenu',
    path: '/role/AssignmentMenu/:id',
    component: () => import(/* webpackChunkName:'role' */ '@/views/role/assignmentMenu'),
    // 设置路径参数
    props: true
  }
src/views/role/son/content.vue,添加分配菜单和资源按钮,设置点击跳转到分配页

.........
<!-- 分配菜单按钮 -->
<el-button type="text" @click="assignmentMenu(scope.row.id)">分配菜单</el-button>
<!-- 分配资源按钮 -->
<el-button type="text">分配资源</el-button>
<!-- 编辑按钮 -->
.............
// 分配菜单按钮点击事件函数
assignmentMenu (id) {
  // 带参数跳转
  this.$router.push({
    name: 'AssignmentMenu',
    params: {
      id
    }
  })
}
src/views/role/assignmentMenu.vue,新建独立组件,在内部书写分配页

<template>
  <div>fenpeicaidan </div>
</template>

<script>
export default {
  //  直接使用路径参数
  props: ['id'],
  created () {
    console.log(this.id)
  }
}
</script>

分配菜单列表展示

使用element树形控件

修改可勾选,默认展开

使用获取所有菜单并按层级展示接口

在页面加载的时候获取所有菜单,直接把接收到的数据设置到data,修改对应关系即可

src/services/menu.js

// 获取所有菜单并按层级展示
export const getMenuNodeList = () => {
  return request({
    method: 'get',
    url: '/boss/menu/getMenuNodeList'
  })
}
src/views/role/assignmentMenu.vue,新建文件展示菜单分配页面

<template>
  <el-card>
    <!-- 树形控件,设置可选择,默认展开 -->
    <el-tree
      :data="data"
      :props="defaultProps"
      @node-click="handleNodeClick"
      default-expand-all
      show-checkbox/>
  </el-card>
</template>

<script>
// 引入 获取全部菜单层级
import { getMenuNodeList } from '@/services/menu'
export default {
  data () {
    return {
      // 树形控件数据
      data: [],
      // 对应关系
      defaultProps: {
        children: 'subMenuList',
        label: 'name'
      }
    }
  },
  // 钩子函数
  created () {
    // 调用方法获取全部层级
    this.getList()
  },
  methods: {
    handleNodeClick (data) {
      console.log(data)
    },
    // 获取全部菜单层级
    async getList () {
      const { data } = await getMenuNodeList()
      if (data.code === '000000') {
        // 获取成功将全部层级数据交给树形控件
        this.data = data.data
      }
    }
  }
}
</script>

分配菜单保存

添加保存和清空按钮

使用给角色分配菜单接口

树形控件提供了方法,可以返回全部选中的数组(使用refs设置),给数分配一个node-key的属性可以把id绑定给节点

保存跳转回页面

// src/services/menu.js

// 给角色分配菜单
export const allocateRoleMenus = data => {
  return request({
    method: 'post',
    url: '/boss/menu/allocateRoleMenus',
    data
  })
}
src/views/role/assignmentMenu.vue

<template>
  <el-card>
    <!-- 树形控件,设置可选择,默认展开,ref、node-key-->
    <el-tree
      ref="tree"
      node-key="id"
      :data="data"
      :props="defaultProps"
      @node-click="handleNodeClick"
      default-expand-all
      show-checkbox/>
    <div style="margin: 20px">
      <el-button>清空</el-button>
      <el-button type="primary" @click="preservation">保存</el-button>
    </div>
  </el-card>
</template>

<script>
// 引入 获取全部菜单层级,分配菜单保存a
import { getMenuNodeList, allocateRoleMenus } from '@/services/menu'
export default {
  // 参数
  props: ['id'],
  // 命名
  name: 'assignment',
  data () {
    return {
      // 树形控件数据
      data: [],
      // 对应关系
      defaultProps: {
        children: 'subMenuList',
        label: 'name'
      },
      // 保存传递参数
      user: {
        roleId: '',
        menuIdList: []
      }
    }
  },
  // 钩子函数
  created () {
    // 调用方法获取全部层级
    this.getList()
  },
  methods: {
    // 保存按钮事件函数
    async preservation () {
      // 设置需要上传的参数
      this.user.menuIdList = this.$refs.tree.getCheckedKeys()
      this.user.roleId = this.id
      // 调用接口
      const { data } = await allocateRoleMenus(this.user)
      if (data.code === '000000') {
        // 如果操作成功,弹出提示。返回角色列表页面
        this.$message({
          message: '保存成功',
          type: 'success'
        })
        this.$router.push('/role')
      }
    },
    // 获取全部菜单层级
    async getList () {
      const { data } = await getMenuNodeList()
      if (data.code === '000000') {
        // 获取成功将全部层级数据交给树形控件
        this.data = data.data
      }
    }
  }
}
</script>

分配菜单展示优化改进

跳转分配菜单功能需要展示当前角色已经分配的菜单

使用获取角色拥有的菜单列表接口

在创建组件的时候自动更换获取已经拥有的菜单

筛选全部选中的菜单id组成数组,如果节点内部还有子节点,那么这个id不需要取出(这里使用递归)

使用树形控件属性可以控制那些节点默认勾选,把数组传递进来

src/views/role/assignmentMenu.vue

<template>
  <el-card>
    <!-- 树形控件,设置可选择,默认展开,ref、node-key,设置默认勾选菜单-->
    <el-tree
      :default-checked-keys="defaultCheckedKeys"
      ref="tree"
      node-key="id"
      :data="data"
      :props="defaultProps"
      default-expand-all
      show-checkbox/>
    <div style="margin: 20px">
      <el-button>清空</el-button>
      <el-button type="primary" @click="preservation">保存</el-button>
    </div>
  </el-card>
</template>

<script>
// 引入 获取全部菜单层级,分配菜单保存,获取用户已拥有菜单
import { getMenuNodeList, allocateRoleMenus, getRoleMenus } from '@/services/menu'
export default {
  // 参数
  props: ['id'],
  // 命名
  name: 'assignment',
  data () {
    return {
      // 树形控件数据
      data: [],
      // 对应关系
      defaultProps: {
        children: 'subMenuList',
        label: 'name'
      },
      // 保存传递参数
      user: {
        roleId: '',
        menuIdList: []
      },
      // 用户已拥有菜单id数组
      defaultCheckedKeys: []
    }
  },
  // 钩子函数
  created () {
    // 调用方法获取全部层级
    this.getList()
    // 获取已拥有菜单
    this.getUserMenu()
  },
  methods: {
    // 遍历全部数组筛选选中的菜单
    screenMenu (data) {
      // 遍历数组
      data.forEach(item => {
        // 如果selected为false,直接返回
        if (!item.selected) {
          return
        }
        // 如果还有子列表,递归调用
        if (item.subMenuList) {
          return this.screenMenu(item.subMenuList)
        }
        // 如果值为true并且没有子菜单,则将id添加到数组中(这里使用ed6语法,因为push会导致不显示)
        this.defaultCheckedKeys = [...this.defaultCheckedKeys, item.id]
      })
    },
    // 获取用户拥有的菜单
    async getUserMenu () {
      // 调用接口获取数据
      const { data } = await getRoleMenus(this.id)
      if (data.code === '000000') {
        // 如果获取数据成功否,调用遍历方法获取全部已拥有菜单
        this.screenMenu(data.data)
      }
    },
    // 保存按钮事件函数
    async preservation () {
      // 设置需要上传的参数
      this.user.menuIdList = this.$refs.tree.getCheckedKeys()
      this.user.roleId = this.id
      // 调用接口
      const { data } = await allocateRoleMenus(this.user)
      if (data.code === '000000') {
        // 如果操作成功,弹出提示。返回角色列表页面
        this.$message({
          message: '保存成功',
          type: 'success'
        })
        this.$router.push('/role')
      }
    },
    // 获取全部菜单层级
    async getList () {
      const { data } = await getMenuNodeList()
      if (data.code === '000000') {
        // 获取成功将全部层级数据交给树形控件
        this.data = data.data
      }
    }
  }
}
</script>

分配菜单清空

点击清空直接使用树形控件的清空方法即可setCheckedKeys

src/views/role/assignmentMenu.vue,在methods中添加方法

................
// 清空勾选列表
empty () {
  // 调用树形结构方法,传入空数组清空列表
  this.$refs.tree.setCheckedKeys([])
},
..................

用户管理

分析与准备工作

筛选、展示和删除不在课程中操作,作为课后作业

使用日期选择器组件

使用分页查询用户信息接口

src/services/user.js

// 分页查询用户信息
export const getUserPages = data => {
  return request({
    method: 'post',
    url: '/boss/user/getUserPages',
    data
  })
}
src/views/user/index.vue - 用户管理页面,引入子组件,将功能写在子组件中

<template>
<!-- 创建子组件实例 -->
  <user-card></user-card>
</template>

<script>
// 引入子组件
import UserCard from './son/card'
export default {
  name: 'user',
  // 注册子组件
  components: {
    UserCard
  }
}
</script>

src/views/user/son/card.vue

<template>
<!-- 容器 -->
  <el-card class="box-card">
    <!-- 卡片头部 -->
    <div slot="header" class="clearfix">
      <!-- form表单 -->
      <el-form :inline="true" :model="formInline" class="demo-form-inline">
        <el-form-item label="手机号">
          <el-input v-model="formInline.phone" placeholder="手机号"></el-input>
        </el-form-item>
        <!-- 日期选择器 -->
        <el-form-item>
          <el-date-picker
            v-model="time"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"/>
        </el-form-item>
        <!-- 查询重置按钮,添加点击事件 -->
        <el-form-item>
          <el-button type="primary" @click="queryUser">查询</el-button>
          <el-button @click="resetUser">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 表格 - 用户展示 -->
    <el-table
      :data="tableData"
      style="width: 100%">
      <el-table-column
        prop="id"
        label="用户ID"/>
      <el-table-column
        label="头像">
        <template slot-scope="scope">
          <!-- 头像使用数据并设置默认值 -->
          <el-avatar size="medium" :src="scope.row.portrait || 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'"></el-avatar>
        </template>
      </el-table-column>
      <el-table-column
        prop="name"
        label="用户名"/>
      <el-table-column
        prop="phone"
        label="手机号"/>
      <el-table-column
        label="注册时间">
        <template slot-scope="scope">
          <!-- 注册时间使用过滤器过滤格式 -->
          <span>{{scope.row.createTime | time}}</span>
        </template>
      </el-table-column>
      <el-table-column
        label="状态">
      </el-table-column>
      <el-table-column
        label="分配角色">
        <!-- 分配角色按钮 -->
        <el-button type="text">分配角色</el-button>
      </el-table-column>
    </el-table>
  </el-card>
</template>

<script>
// 引入 - 分页查询用户信息
import { getUserPages } from '@/services/user'
export default {
  // 组件命名
  name: 'userCard',
  data () {
    return {
      // 接口查询用户信息数据
      formInline: {
        phone: null
      },
      // 日期选择器数据
      time: '',
      // 用户列表数据
      tableData: []
    }
  },
  // 钩子函数
  created () {
    // 初始化获取用户数据
    this.getUser(this.formInline)
  },
  methods: {
    // 重置按钮事件函数
    resetUser () {
      // 重置数据
      this.time = []
      this.formInline.phone = null
    },
    // 查询按钮事件函数
    queryUser () {
      // 根据是否选择日期传递不同的参数
      if (this.time && this.time.length === 2) {
        this.getUser({
          phone: this.formInline.phone,
          startCreateTime: this.time[0],
          endCreateTime: this.time[1]
        })
      } else {
        this.getUser(this.formInline)
      }
    },
    // 获取用户数据
    async getUser (obj) {
      // 获取数据
      const { data } = await getUserPages(obj)
      if (data.code === '000000') {
        // 如果获取成功,将数据交给列表
        this.tableData = data.data.records
      }
    }
  },
  // 过滤器
  filters: {
    // 时间过滤器,用于过滤表格中的用户注册时间
    time (data) {
      // 直接截取前10位字符串
      return data.slice(0, 10)
    }
  }
}
</script>

分配角色布局

使用对话框组件

使用下拉菜单组件(可多选)

src/views/user/son/card.vue - 添加静态布局(对话框+多选选择器)

<template>
<!-- 容器 -->
  <el-card class="box-card">
    <!-- 卡片头部 -->
    <div slot="header" class="clearfix">
      <!-- form表单 -->
      <el-form :inline="true" :model="formInline" class="demo-form-inline">
        <el-form-item label="手机号">
          <el-input v-model="formInline.phone" placeholder="手机号"></el-input>
        </el-form-item>
        <!-- 日期选择器 -->
        <el-form-item>
          <el-date-picker
            v-model="time"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"/>
        </el-form-item>
        <!-- 查询重置按钮,添加点击事件 -->
        <el-form-item>
          <el-button type="primary" @click="queryUser">查询</el-button>
          <el-button @click="resetUser">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 表格 - 用户展示 -->
    <el-table
      :data="tableData"
      style="width: 100%">
      <el-table-column
        prop="id"
        label="用户ID"/>
      <el-table-column
        label="头像">
        <template slot-scope="scope">
          <!-- 头像使用数据并设置默认值 -->
          <el-avatar size="medium" :src="scope.row.portrait || 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'"></el-avatar>
        </template>
      </el-table-column>
      <el-table-column
        prop="name"
        label="用户名"/>
      <el-table-column
        prop="phone"
        label="手机号"/>
      <el-table-column
        label="注册时间">
        <template slot-scope="scope">
          <!-- 注册时间使用过滤器过滤格式 -->
          <span>{{scope.row.createTime | time}}</span>
        </template>
      </el-table-column>
      <el-table-column
        label="状态">
      </el-table-column>
      <el-table-column
        label="分配角色">
        <!-- 分配角色按钮 -->
        <el-button type="text" @click="assignroles">分配角色</el-button>
      </el-table-column>
    </el-table>
    <!-- 对话框 -->
    <el-dialog
      title="分配角色"
      :visible.sync="dialogVisible"
      width="50%">
      <!-- 选择器,绑定数据,multiple开启多选 -->
      <el-select v-model="roltList" multiple placeholder="选择要分配的角色">
        <el-option
          v-for="item in options"
          :key="item.value"
          :label="item.name"
          :value="item.id">
        </el-option>
      </el-select>
      <!-- 取消和确定按钮 -->
      <span slot="footer" class="dialog-footer">
        <el-button>取 消</el-button>
        <el-button type="primary">确 定</el-button>
      </span>
    </el-dialog>
  </el-card>
</template>

<script>
// 引入 - 分页查询用户信息
import { getUserPages } from '@/services/user'
export default {
  // 组件命名
  name: 'userCard',
  data () {
    return {
      // 接口查询用户信息数据
      formInline: {
        phone: null
      },
      // 日期选择器数据
      time: '',
      // 用户列表数据
      tableData: [],
      // 信号值 - 控制对话框显示隐藏
      dialogVisible: false,
      // 选择器选项数据
      options: [],
      // 选择器选择结果
      roltList: []
    }
  },
  // 钩子函数
  created () {
    // 初始化获取用户数据
    this.getUser(this.formInline)
  },
  methods: {
    // 分配角色按钮事件函数
    assignroles () {
      this.dialogVisible = true
    },
    // 重置按钮事件函数
    resetUser () {
      // 重置数据
      this.time = []
      this.formInline.phone = null
    },
    // 查询按钮事件函数
    queryUser () {
      // 根据是否选择日期传递不同的参数
      if (this.time && this.time.length === 2) {
        this.getUser({
          phone: this.formInline.phone,
          startCreateTime: this.time[0],
          endCreateTime: this.time[1]
        })
      } else {
        this.getUser(this.formInline)
      }
    },
    // 获取用户数据
    async getUser (obj) {
      // 获取数据
      const { data } = await getUserPages(obj)
      if (data.code === '000000') {
        // 如果获取成功,将数据交给列表
        this.tableData = data.data.records
      }
    }
  },
  // 过滤器
  filters: {
    // 时间过滤器,用于过滤表格中的用户注册时间
    time (data) {
      // 直接截取前10位字符串
      return data.slice(0, 10)
    }
  }
}
</script>

展示角色列表

使用获取所有角色接口

// src/services/user.js - 封装获取所有可分配角色

// 获取所有用户可以分配的角色
export const getAllRole = () => {
  return request({
    method: 'get',
    url: '/boss/role/all'
  })
}
// src/views/user/son/card.vue - 修改分配按钮点击事件获取全部可分配角色数据

//分配角色按钮事件函数
async assignroles () {
  // 显示对话框
  this.dialogVisible = true
  // 获取全部可分配角色列表
  const { data } = await getAllRole()
  if (data.code === '000000') {
    // 将所有角色交给选择器
    this.options = data.data
  }
}

提交分配角色

点击分配关闭对话框

使用为用户分配角色接口

src/views/user/son/card.vue - 确定按钮添加事件,取消按钮事件函数直接写在行内(this.dialogVisible = false// 分配角色确定按钮点击事件
async PerformAssignmentRoles () {
  // 调用接口为用户设置角色
  const { data } = await allocateUserRoles({
    userId: this.userId,
    roleIdList: this.roltList
  })
  if (data.code === '000000') {
    // 如果设置成功,弹出提示,并关闭对话框
    this.$message({
      message: '保存成功',
      type: 'success'
    })
    this.dialogVisible = false
  }
}
// src/services/user.js - 封装接口

// 给用户分配角色
export const allocateUserRoles = data => {
  return request({
    method: 'post',
    url: '/boss/role/allocateUserRoles',
    data
  })
}

默认选中已分配角色

使用查询用户角色接口

自动查询当前用户有哪些角色

把角色分配给下拉菜单

// src/services/user.js

// 引入接口模块
import request from '@/utils/request'
// 引入qs插件
import qs from 'qs'

// 用户登录
// data为参数
export const login = (data) => {
  // 使用接口模块
  return request({
    // post方法
    method: 'post',
    // 接口地址
    url: '/front/user/login',
    // 使用qs转换参数
    data: qs.stringify(data)
  })
}

// 用户信息获取模块
export const getUserInfo = () => {
  return request({
    // get方法
    method: 'get',
    // 接口地址
    url: '/front/user/getInfo'
  })
}

// 分页查询用户信息
export const getUserPages = data => {
  return request({
    method: 'post',
    url: '/boss/user/getUserPages',
    data
  })
}

// 获取所有用户可以分配的角色
export const getAllRole = () => {
  return request({
    method: 'get',
    url: '/boss/role/all'
  })
}

// 给用户分配角色
export const allocateUserRoles = data => {
  return request({
    method: 'post',
    url: '/boss/role/allocateUserRoles',
    data
  })
}

// 查询用户角色
export const getUserRole = userId => {
  return request({
    method: 'get',
    url: `/boss/role/user/${userId}`
  })
}

src/views/user/son/card.vue - 使用查询用户角色接口查询用户角色,然后把角色传递给选择器实现默认勾选

<template>
<!-- 容器 -->
  <el-card class="box-card">
    <!-- 卡片头部 -->
    <div slot="header" class="clearfix">
      <!-- form表单 -->
      <el-form :inline="true" :model="formInline" class="demo-form-inline">
        <el-form-item label="手机号">
          <el-input v-model="formInline.phone" placeholder="手机号"></el-input>
        </el-form-item>
        <!-- 日期选择器 -->
        <el-form-item>
          <el-date-picker
            v-model="time"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"/>
        </el-form-item>
        <!-- 查询重置按钮,添加点击事件 -->
        <el-form-item>
          <el-button type="primary" @click="queryUser">查询</el-button>
          <el-button @click="resetUser">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 表格 - 用户展示 -->
    <el-table
      :data="tableData"
      style="width: 100%">
      <el-table-column
        prop="id"
        label="用户ID"/>
      <el-table-column
        label="头像">
        <template slot-scope="scope">
          <!-- 头像使用数据并设置默认值 -->
          <el-avatar size="medium" :src="scope.row.portrait || 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'"></el-avatar>
        </template>
      </el-table-column>
      <el-table-column
        prop="name"
        label="用户名"/>
      <el-table-column
        prop="phone"
        label="手机号"/>
      <el-table-column
        label="注册时间">
        <template slot-scope="scope">
          <!-- 注册时间使用过滤器过滤格式 -->
          <span>{{scope.row.createTime | time}}</span>
        </template>
      </el-table-column>
      <el-table-column
        label="状态">
      </el-table-column>
      <el-table-column
        label="分配角色">
        <template slot-scope="scope">
          <!-- 分配角色按钮 -->
          <el-button type="text" @click="assignroles(scope.row.id)">分配角色</el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 对话框 -->
    <el-dialog
      title="分配角色"
      :visible.sync="dialogVisible"
      width="50%">
      <!-- 选择器,绑定数据,multiple开启多选 -->
      <el-select v-model="roltList" multiple placeholder="选择要分配的角色">
        <el-option
          v-for="item in options"
          :key="item.value"
          :label="item.name"
          :value="item.id">
        </el-option>
      </el-select>
      <!-- 取消和确定按钮 -->
      <span slot="footer" class="dialog-footer">
        <!-- 取消按钮事件函数直接写在行内 -->
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="PerformAssignmentRoles">确 定</el-button>
      </span>
    </el-dialog>
  </el-card>
</template>

<script>
// 引入 - 分页查询用户信息、获取用户全部可分配角色、给用户分配角色、查询用户角色
import { getUserPages, getAllRole, allocateUserRoles, getUserRole } from '@/services/user'
export default {
  // 组件命名
  name: 'userCard',
  data () {
    return {
      // 接口查询用户信息数据
      formInline: {
        phone: null
      },
      // 日期选择器数据
      time: '',
      // 用户列表数据
      tableData: [],
      // 信号值 - 控制对话框显示隐藏
      dialogVisible: false,
      // 选择器选项数据
      options: [],
      // 选择器选择结果
      roltList: [],
      // 信号值 - 标记当前用户id
      userId: ''
    }
  },
  // 钩子函数
  created () {
    // 初始化获取用户数据
    this.getUser(this.formInline)
  },
  methods: {
    // 分配角色确定按钮点击事件
    async PerformAssignmentRoles () {
      // 调用接口为用户设置角色
      const { data } = await allocateUserRoles({
        userId: this.userId,
        roleIdList: this.roltList
      })
      if (data.code === '000000') {
        // 如果设置成功,弹出提示,并关闭对话框
        this.$message({
          message: '保存成功',
          type: 'success'
        })
        this.dialogVisible = false
      }
    },
    // 分配角色按钮事件函数
    async assignroles (id) {
      // 修改当前用户id
      this.userId = id
      // 显示对话框
      this.dialogVisible = true
      // 获取全部可分配角色列表
      const { data } = await getAllRole()
      if (data.code === '000000') {
        // 将所有角色交给选择器
        this.options = data.data
      }
      // 获取当前用户角色
      const { data: data2 } = await getUserRole(id)
      if (data2.code === '000000') {
        // 如果获取成功,遍历全部角色,将角色id传给下拉菜单
        data2.data.forEach(item => {
          this.roltList.push(item.id)
        })
      }
    },
    // 重置按钮事件函数
    resetUser () {
      // 重置数据
      this.time = []
      this.formInline.phone = null
    },
    // 查询按钮事件函数
    queryUser () {
      // 根据是否选择日期传递不同的参数
      if (this.time && this.time.length === 2) {
        this.getUser({
          phone: this.formInline.phone,
          startCreateTime: this.time[0],
          endCreateTime: this.time[1]
        })
      } else {
        this.getUser(this.formInline)
      }
    },
    // 获取用户数据
    async getUser (obj) {
      // 获取数据
      const { data } = await getUserPages(obj)
      if (data.code === '000000') {
        // 如果获取成功,将数据交给列表
        this.tableData = data.data.records
      }
    }
  },
  // 过滤器
  filters: {
    // 时间过滤器,用于过滤表格中的用户注册时间
    time (data) {
      // 直接截取前10位字符串
      return data.slice(0, 10)
    }
  },
  watch: {
    dialogVisible (newvalue) {
      if (!newvalue) {
        this.roltList = []
      }
    }
  }
}
</script>