vue2人力资源项目7员工管理

页面结构

树形组件

    <el-tree :data="depts" :props="defaultProps" :default-expand-all="true" />

 记录节点

设置变量以存储查询参数

// 存储查询参数
      queryParams: {
        departmentId: null
      }

找到节点——>记录节点——>调用setCurrentKey方法选中节点

初始化时,找到首个节点记录并且选中(因为我们设置完树形之后立刻选中首个节点,此时更新还没有完成,必须等待更新完成后,再去选中首个节点,所以需要使用$nextTick)

 methods: {
    async getDepartment() {
      // 调用封装好的转换树的方法

      this.depts = transListToTreeData(await getDepartment(), 0)
      this.queryParams.departmentId = this.depts[0].id
this.$nextTick(() => {
        // 此时意味着树渲染完毕
        //选中
this.$refs.deptTree.setCurrentKey(this.queryParams.departmentId)
      }
      )
    }
    }
  }

选中时,记录节点

 <el-tree
          ref="deptTree"
          :data="depts"
          :props="defaultProps"
          :default-expand-all="true"
          node-key="id"
          @current-change="selectNode"
        />
 // 记录节点
    selectNode(node) {
      this.queryParams.departmentId = node.id
    }

员工列表结构:

表格样式

 <!-- 表格组件 -->
        <el-table>
          <el-table-column alien="center" label="头像" />
          <el-table-column label="姓名" />
          <el-table-column label="手机号" sortable />
          <el-table-column label="工号" sortable />
          <el-table-column label="聘用形势" />
          <el-table-column label="入职时间" sotrable />
          <el-table-column label="操作" width="280px">
            <template>
              <button size="mini" type="text">查看</button>
              <button size="mini" type="text">角色</button>
              <button size="mini" type="text">删除</button>
            </template>
          </el-table-column>
        </el-table>

分页模式

 <!-- 分页 -->
        <el-row type="flex" style="height: 60px;" align="middle" justify="end">
          <el-pagination layout="total,prev, pager, next" :total="1000" />
        </el-row>

数据渲染

1.首次加载

1.1 封装api,封装获取数据的方法,list已经提取定义好

// 获取员工列表的方法
    async getEmployeeList() {
      const { rows } = await getEmployeeList(this.queryParams)
      this.list = rows
    }
  }

1.2给表格绑定数据

   <el-table :data="list">

1.3给每一列指定数据

          <el-table-column alien="center" prop="staffPhoto" label="头像" />
          <el-table-column label="姓名" paop="username" />

1.4 调用方法渲染

async getDepartment() {
      // 调用封装好的转换树的方法

      this.depts = transListToTreeData(await getDepartment(), 0)
      this.queryParams.departmentId = this.depts[0].id
      // 设置选中节点
      // 树组件渲染是异步的 等到更新完毕
      this.$nextTick(() => {
        // 此时意味着树渲染完毕
        this.$refs.deptTree.setCurrentKey(this.queryParams.departmentId)
      }
      )

      // 这个时候参数 记录了id
      // 调用了获取员工列表的方法
      this.getEmployeeList()
    },

2.切换节点重新渲染

2.1 节点id更新之后又重新调方法即可

   this.$nextTick(() => {
        // 此时意味着树渲染完毕
        this.$refs.deptTree.setCurrentKey(this.queryParams.departmentId)
      }
      )

      // 这个时候参数 记录了id
      // 调用了获取员工列表的方法
      this.getEmployeeList()
    },
    // 记录节点
    selectNode(node) {
      this.queryParams.departmentId = node.id
      this.getEmployeeList()
    },

对显示出来的数据进行处理

1.头像

row指的是当前行的数据

 <el-table-column alien="center" prop="staffPhoto" label="头像">
            <template v-slot="{row}">
              <el-avatar v-if="row.staffPhoto" :src="row.staffPhoto" :size="30" />
              <span v-else class="username">{{ row.username.charAt(0) }}</span>
            </template>

2.聘用形势

 <el-table-column label="聘用形势" />
          <template v-slot="{row}">
            <span v-if="row.formOfEmployment === 1">正式</span>
            <span v-else-if="row.formOfEmployment === 2">非正式</span>
            <span v-else>无</span>
          </template>

3.总结

分页 

先获取total数据,并且赋值给设定好的变量,再赋值给分页组件

 async getEmployeeList() {
      const { rows, total } = await getEmployeeList(this.queryParams)
      this.list = rows
      this.total = total
    }
  }
  list: [],
      total: '0'
 <!-- 分页 -->
        <el-row type="flex" style="height: 60px;" align="middle" justify="end">
          <el-pagination layout="total,prev, pager, next" :total="total" />
        </el-row>

 在queryParams里加入两个分页参数

// 存储查询参数
      queryParams: {
        departmentId: null,
        page: 1,
        pagesize: 10
      }

 把添加的参数绑定到分页组件上,同时绑定change事件

<el-row type="flex" style="height: 60px;" align="middle" justify="end">
          <el-pagination layout="total,prev, pager, next" :total="total" :current-page="queryParams.page"  @current-change="changePage"/>
        </el-row>

change方法的逻辑

changePage(newPage) {
      this.queryParams.page = newPage// 赋值新页码
      this.getEmployeeList()// 查询数据
    }

切换节点时,重置为第一页

 // 记录节点
    selectNode(node) {
      this.queryParams.departmentId = node.id
      this.queryParams.page = 1// 设置第一页
      this.getEmployeeList()
    }

中文版 element-ui

// set ElementUI lang to EN
Vue.use(ElementUI, { locale })
// 如果想要中文版 element-ui,按如下方式声明
// Vue.use(ElementUI)

这个引用也要注释

// import locale from 'element-ui/lib/locale/lang/en' // lang i18n

实现员工查询

1.设置参数

// 存储查询参数
      queryParams: {
        departmentId: null,
        page: 1,
        pagesize: 10,
        keyword: ''
      }

2.给输入框绑定参数和事件(输入框内容一变化就触发)

 <el-input
          v-model="queryParams.keyword"
          style="margin-bottom:10px"
          type="text"
          prefix-icon="el-icon-search"
          size="small"
          placeholder="输入员工姓名全员搜索"
          @input="changeValue"
        />

3.事件逻辑(防抖处理)

 changeValue() {
      // 单位时间内只会执行最后一次
      // this的实例上赋值了一个timer的属性
      clearTimeout(this.timer)// 清楚上一次的定时器
      this.timer = setTimeout(() => {
        // 先把页数设置为第一页
        this.queryParams.page = 1
        // 调用方法重新渲染
        getEmployeeList()
      }, 300)
    }

员工导出excel

1.封装导excel接口:注意返回的字符形式需要转换

// 导出员工的excel
export function exportEmployee() {
  return request({
    url: '/sys/user/export',
    // 改变接收数据的类型
    responseType: 'blob'// 使用blob接收二进制文件流
  })
}

2.响应拦截器判断是否是blob格式

// 响应拦截器
service.interceptors.response.use((response) => {
  // 判断是不是Blob
  if (response.data instanceof Blob) return response.data// 返回了Blob对象
  const { data, message, success } = response.data
  if (success) {
    return data
  } else {
    Message({ type: 'error', message })
    return Promise.reject(new Error(message))// 这里没有传入error,所以新建了一个Error对象,在传信息
  }
}

3.下载文件

命令台

 npm i file-saver
  async exportEmployee() {
      // 调用接口
      const result = await exportEmployee()
      // 使用一个npm包,直接将blob文件下载到本地
      // 之后引入这个包
      // 调用方法保存下来
      // 引入的包名.saveAs(blob对象,文件名称)
      FileSaver.saveAs(result, '员工信息表.xlsx')
    }

excel导入组件

1.创建组件,把组件模板粘贴过来

<template>
  <el-dialog
    width="500px"
    title="员工导入"
    :visible="showExcelDialog"
    @close="$emit('update:showExcelDialog', false)"
  >
    <el-row type="flex" justify="center">
      <div class="upload-excel">
        <input
          ref="excel-upload-input"
          class="excel-upload-input"
          type="file"
          accept=".xlsx, .xls"
        >
        <div class="drop">
          <i class="el-icon-upload" />
          <el-button type="text">下载导入模板</el-button>
          <span>将文件拖到此处或
            <el-button type="text">点击上传</el-button>
          </span>
        </div>
      </div>
    </el-row>
    <el-row type="flex" justify="end">
      <!-- update:props属性名,值 直接修改 .sync修饰符的属性值 -->
      <el-button size="mini" type="primary" @click="$emit('update:showExcelDialog', false)">取消</el-button>
    </el-row>
  </el-dialog>
</template>
<script>

export default {
  props: {
    showExcelDialog: {
      type: Boolean,
      default: false
    }
  },
  methods: {

  }
}
</script>

<style scoped lang="scss">
    .upload-excel {
      display: flex;
      justify-content: center;
      margin: 20px;
      width: 360px;
      height: 180px;
      align-items: center;
      color: #697086;
      .excel-upload-input {
        display: none;
        z-index: -9999;
      }
      .btn-upload,
      .drop {
        border: 1px dashed #dcdfe6;
        width: 100%;
        height: 100%;
        text-align: center;
        line-height: 160px;
        border-radius: 8px;
        display: flex;
        flex-direction: column;
        justify-content: center;
      }
      .drop {
        line-height: 40px;
        color: #bbb;
        i {
          font-size: 60px;
          display: block;
          color: #c0c4cc;
        }
      }
    }
</style>

2.在index.vue里引入组件,并注册 

import ImportExcel from './components/import-excel.vue'
export default {
  name: 'Employee',
  components
  data() {
    return {
      depts: [],
      components:{
        ImportExcel
      },

3.index里放置组件

  <!--放置导入组件-->
    <import-excel></import-excel>

4.数据准备

 list: [],
      total: '0',
      showExcelDialog:false//控制弹层的显示和隐藏
    }

5.给组件绑定事件

可以通过:show-excel-dialog.sync这个属性接收显示Excel对话框的状态(例如布尔值),也可以通过发出一个事件来更新父组件中的showExcelDialog状态。

.sync:当子组件import-excel需要更新父组件中的showExcelDialog状态时,它会通过.sync修饰符自动同步这些变更,无需父组件手动处理这些更新。

 </div>
    <!--放置导入组件-->
    <import-excel :show-excel-dialog.sync = "showExcelDialog"/>
  </div>

6.点击按钮显示弹层

          <el-button size="mini" @click="showExcelDialog=true">excel导入</el-button>

excel下载导入模板

 1.封装接口:返回的是Blob要加responseType

// 下载导入员工模板
export function getExportTemplate() {
  return request({
    url: '/sys/user/import/template',
    responseType: 'blob'// 二进制文件流
  })
}

2.调用方法,获取Blob,使用第三方包FileSaver来saveAs

 methods: {
    async  getTemplate() {
      const data = await getExportTemplate()
      FileSaver.saveAs(data, '员工导入模板.xlsx')
    }
  }

excel导入

1.利用input弹出文件选择器:click()函数是这个DOM元素的原生方法,用于模拟用户对该元素的点击动作。

 <el-button type="text" @click="handleUpload">点击上传</el-button>
handleUpload() {
      // 弹出文件选择题-只有一种方式,通过input file
      this.$refs['excel-upload-input'].click()
      // this.$refs.属性名 和 this.$refs[属性名] 等价
    }
<input
          ref="excel-upload-input"
          class="excel-upload-input"
          type="file"
          accept=".xlsx, .xls"
          @change="uploadChange"
        >

封装接口:这里是formdata类型,需要  在组件里 const data = new FormData()

// 上传用户的excel
export function uploadExcel(data
) {
  return request({
    url: '/sys/user/import',
    method: 'post',
    data // form-data类型 因为要上传文件类型
  })
}

方法里调用接口与处理

   async uploadChange(event) {
      // @change="uploadChange"传过来的event
      // 调用接口

      const files = event.target.files// input的文件列表
      if (files.length > 0) {
        // 大于0,说明有文件要上传
        const data = new FormData()
        // file:file类型
        data.append('file', files[0])

        try {
          // 把data传给接口
          await uploadExcel(data)
          // 处理成功和失败
          // 成功后关闭弹层
          this.$emit('uploadSuccess')// 通知父组件 我上传成功
          this.$emit('update:showExcelDialog', false)// 关闭弹层
        } catch (error) {
          // 捕获失败

        } finally {
          // 无论成功或失败都会执行finally的清空
          // 因为名字是excel-upload-input,所以使用了this.$refs[属性名]
          this.$refs['excel-upload-input'].value = ''
        }
      }
    }

父组件监听uploadSuccess事件,@uploadSuccess是一个事件监听器,用来监听文件上传成功的事件。它会在文件上传成功时被触发。

    <import-excel :show-excel-dialog.sync="showExcelDialog" @uploadSuccess="getEmployeeList" />

 删除员工

弹窗

 <button size="mini" type="text">查看</button>
              <button size="mini" type="text">角色</button>
              <el-popconfirm
                title="Are you sure to delete this?"
                @OnConfirm="confirmDel(row.id)"
              >

    删除员工的方法

 async    confirmDel(id) {
await delEmployee(id)
if(this.list.length === 1 && this.queryParams.page > 1){
  this.queryParams.page--
  this.getEmployeeList()
  this.$message.success('成功')
}
}

封装的接口

// 删除员工的方法
export function delEmployee(id) {
  return request({
    url: `/sys/user/${id}`,
    method: 'delete'
  })
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值