5.2 iHRM人力资源 - 员工管理 - 使用文件导入导出员工

iHRM人力资源 - 员工管理 - 导入导出员工

一、员工导出Excel

这个地方涉及一个接口二进制流blob

image-20240408204202305

就是下面这一大片乱七八糟的玩意(二进制文件流),接收完流后通过下载的方式将文件下载下载(图片左下方)

image-20240408204336372

总结步骤

image-20240408205238034

  1. api方法
/**
 * 导出员工的Excel
 */
export function exportEmployee() {
  return request({
    url: '/sys/user/export',
    // 接收二进制流类型的数据需要改变axios的接收数据类型
    // 使用blob接收二进制文件流
    responseType: 'blob'
  })
}
  1. 点击事件
<el-button size="mini" @click="exportEmployee">excel导出</el-button>
// 导出员工的Excel
async exportEmployee() {
  await exportEmployee()
}
  1. 修改响应拦截器

因为返回的不是JSON数据了,所以我们要处理一下

image-20240408210135899

// 创建响应拦截器,并且两个参数都是回调函数
service.interceptors.response.use(
  // 请求成功时响应,此时的响应默认包裹了一层data,即response.data才是后台服务返回的内容
  (response) => {
    // 首先判断响应的数据是JSON格式数据还是blob二进制文件流
    if (response.data instanceof Blob) {
      // 我们认为此时接口返回的是文件
      return response.data
    }
    // 一次性解析出response.data中的三个属性
    const { data, message, success } = response.data // 默认是JSON数据,假如不是JSON数据的话就会报错
    if (success) {
      // 此时响应正常
      return data
    } else {
      Message({ type: 'error', message: message })
      return Promise.reject(new Error(message))
    }
  },
  // 请求失败时响应
  async(error) => {
    if (error.response.status === 401) {
      Message({ type: 'warning', message: 'token 超时了,请重新登录' })
      // token超时,调用action退出登录(删除用户信息)
      // dispatch返回的是一个promise,这里会等dispatch执行完再执行路由跳转
      await store.dispatch('user/logout')
      // 主动跳转到登录页
      router.push('/login')
      return Promise.reject(error)
    }
    // this.$message.warning 不能这么使用,因为此时的this不是组件实例对象
    Message({ type: 'error', message: error.message })
    // 默认支持promise的,下面语句相当于终止了当前promise的执行
    return Promise.reject(error)
  }
)
  1. 用blob接收后就需要保存文件或者说下载文件

首先执行命令下载工具包

npm i file-saver

image-20240408210825522

导入包

import FileSaver from 'file-saver'

修改方法

// 导出员工的Excel
async exportEmployee() {
  const result = await exportEmployee()
  // 使用一个npm包,将blob文件下载到本地 执行命令 npm i file-saver
  // 使用下面这个另存为的方法
  // 参数1:blob对象,参数2:文件名称
  FileSaver.saveAs(result, '员工信息表.xlsx') // 下载二进制文件到浏览器
}

二、员工导入Excel

如下图所示,用户需要按照模板样式上传Excel表格

image-20240408213914913

模板内容如下图所示

image-20240408214022575

流程如下图所示

image-20240408214206465

2.1 Excel导入组件封装

创建组件

image-20240408214332654

  1. 组件内的基本架构
<template>
  <!--弹层部分-->
  <!--visible 控制是否显示-->
  <el-dialog
    width="500px"
    title="员工导入"
    :visible="showExcelDialog"
    @close="$emit('update:showExcelDialog', false)"
  >
    <el-row type="flex" justify="center">
      <div class="upload-excel">
        <!--文本输入框的类型是file,可以接收的文件类型.xlsx或者.xls-->
        <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修饰符的属性值-->
      <!-- 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>

  1. 在index.vue文件中引入组件
// 引入自定义的组件
import ImportExcel from '@/views/employee/import-excel.vue'
export default {
  name: 'Employee',
  components: {
    ImportExcel
  },
    ......
}
<!--放置导入Excel组件--> 
<import-excel></import-excel>
  1. 控制自定义组件的显示和隐藏
<!--放置导入Excel组件-->
<!--sync修饰符,我们点击关闭弹层或者取消的时候,会自然的把父组件的值改掉-->
<import-excel :show-excel-dialog.sync="showExcelDialog"></import-excel>

数据

      // 控制Excel弹层的显示和隐藏
      showExcelDialog: false

此时弹框的取消和关闭是管用的

image-20240408230640601

  1. 点击按钮弹出弹层
<el-button size="mini" @click="showExcelDialog=true">excel导入</el-button>

2.2 下载导入模板

如下图所示的按钮,点击下载一个Excel模板

image-20240408231002314

这个地方和“导出员工Excel”差不多的形式

image-20240409113511140

  1. api请求
/**
 * 下载员工的导入模板
 */
export function getExportTemplate() {
  return request({
    url: '/sys/user/import/template',
    // 接收二进制流类型的数据需要改变axios的接收数据类型
    // 使用blob接收二进制文件流
    responseType: 'blob'
  })
}
  1. 在我们封装的组件里填写点击“下载导入模板”后,下载模板

    image-20240409144354041

<div class="drop">
  <i class="el-icon-upload"/>
  <el-button type="text" @click="getTemplate">下载导入模板</el-button>
  <span>将文件拖到此处或
    <el-button type="text">点击上传</el-button>
  </span>
</div>

方法

import FileSaver from 'file-saver'
  methods: {
    // 下载导入模板
    async getTemplate() {
      const result = await getExportTemplate()
      // console.log(result) // 使用一个npm包 直接将blob文件下载到本地 file-saver
      // FileSaver.saveAs(blob对象,文件名称)
      FileSaver.saveAs(result, '员工导入模板.xlsx') // 下载文件(另存为)
    }
  }
  1. 效果

    挺完美的

image-20240409144740165

2.3 Excel 导入功能

下面将实现这个功能

image-20240409145125735

流程如下图所示

为什么要清空?

因为我们使用了一个input框,所以关闭或者上传后要清空内容

image-20240409145422610

  1. 点击上传按钮,弹出文件选择器
<el-row type="flex" justify="center">
  <div class="upload-excel">
    <!--文本输入框的类型是file,可以接收的文件类型.xlsx或者.xls-->
    <!--当我们点击“点击上传”按钮后,下面的input框就应该弹出来-->
    <!--有了ref,我们就能获取input框中的DOM对象-->
    <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" @click="getTemplate">下载导入模板</el-button>
      <span>将文件拖到此处或
        <el-button type="text" @click="handleUpload">点击上传</el-button>
      </span>
    </div>
  </div>
</el-row>

方法

// 弹出文件选择器 - 只有一种方式,通过input框中的file属性
handleUpload() {
  // input框只要触发了点击事件,就会弹出文件选择器
  this.$refs['excel-upload-input'].click() // 这种写法和this.$refs.属性名是一样的
}

效果

image-20240409150429074

  1. 将文件进行上传

    请求参数如下所示

    现在的参数不是JSON了,而是form-data

image-20240409151519249

api方法

/**
 * 上传Excel接口
 */
export function uploadExcel(data) {
  return request({
    url: '/sys/user/import/template',
    method: 'post',
    // 此处的data是form-data类型,因为要上传文件,不是JSON类型
    data: data
  })
}

按钮

<!--文本输入框的类型是file,可以接收的文件类型.xlsx或者.xls-->
<!--当我们点击“点击上传”按钮后,下面的input框就应该弹出来-->
<!--有了ref,我们就能获取input框中的DOM对象-->
<!--当我们选择上传文件后,就会触发@change事件-->
<input
  ref="excel-upload-input"
  class="excel-upload-input"
  type="file"
  accept=".xlsx, .xls"
  @change="uploadChange"
>

方法

// 当触发@change事件的时候,会传过来一个event
// event.target是事件源,也就是我们的input
// 在event.target对象中,有一个files数组,数组中的每一个对象都是一个file对象
async uploadChange(event) {
  const files = event.target.files // input的文件列表
  // 判断文件的长度,没有的话就不上传了
  if (files.length > 0) {
    // 调用上传接口
    // 参数是form-data类型,需要文件file
    const data = new FormData()
    // files[0] 文件
    data.append('file', files[0]) // 将文件的参数加入到form-data中
    try {
      await uploadExcel(data)
      // 此时一定是响应成功的,成功之后要重新加载数据(重新加载index页面的数据,并不是这个组件的)
      this.$emit('uploadSuccess')// 通知父组件,上传成功
      // 关闭弹层
      this.$emit('update:showExcelDialog', false)
      // 清空文件选择器
      // this.$refs['excel-upload-input'].value = ''
    } catch (error) {
      // 捕获失败
      // 清空文件选择器
      // this.$refs['excel-upload-input'].value = ''
    } finally {
      // 清空文件选择器
      this.$refs['excel-upload-input'].value = ''
    }
  }
}

image-20240409190321436

index页面中的组件

<!--放置导入Excel组件-->
<!--sync修饰符,我们点击关闭弹层或者取消的时候,会自然的把父组件的值改掉-->
<!--@uploadSuccess 表示监听子组件的uploadSuccess,监听到就重新加载页面数据-->
<import-excel :show-excel-dialog.sync="showExcelDialog" @uploadSuccess="getEmployeeList"></import-excel>

三、删除员工

image-20240409203535656

如下图所示

image-20240409193027926

流程如下所示

image-20240409203507745

  1. 按钮
<el-table-column label="操作" width="280px">
  <!--插槽-->
  <template v-slot="{row}">
    <!--type="text"表示按钮是链接的形式-->
    <el-button size="mini" type="text">查看</el-button>
    <el-button size="mini" type="text">角色</el-button>
    <!--气泡确认框-->
    <!--点击确认后会执行 @onConfirm-->
    <el-popconfirm title="这段内容确定要删除吗?" @onConfirm="confirmDel(row.id)">
      <el-button slot="reference" style="margin-left: 10px" size="mini" type="text">删除</el-button>
    </el-popconfirm>
  </template>
</el-table-column>
  1. api方法
/**
 * 删除员工的接口
 */
export function delEmployee(id) {
  return request({
    url: `/sys/user/${id}`,
    method: 'delete'
  })
}
  1. 方法
async confirmDel(id) {
  await delEmployee(id)
  // 判断是不是当前页的最后一个
  if (this.list.length === 1 && this.queryParams.page > 1) {
    this.queryParams.page--
  }
  // 重新获取部门数据
  getEmployeeList()
  this.$message.success('删除用户成功')
}
argin-left: 10px" size="mini" type="text">删除</el-button>
    </el-popconfirm>
  </template>
</el-table-column>
  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我爱布朗熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值