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

本文详细描述了如何在iHRM系统中实现员工的Excel导入导出功能,包括导出员工数据到Excel,使用file-saver下载文件,以及员工Excel导入过程中的组件封装和错误处理。同时介绍了删除员工的操作和API接口的使用。
摘要由CSDN通过智能技术生成

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
    评论
https://pan.baidu.com/s/1rlumdezlSwOvFXgG8ypUJQ /** * 导入Excel,添加用户 * 文件上传:springboot */ @RequestMapping(value="/user/import",method = RequestMethod.POST) public Result importUser(@RequestParam(name="file") MultipartFile file) throws Exception { //1.解析Excel //1.1.根据Excel文件创建工作簿 Workbook wb = new XSSFWorkbook(file.getInputStream()); //1.2.获取Sheet Sheet sheet = wb.getSheetAt(0);//参数:索引 //1.3.获取Sheet中的每一行,和每一个单元格 //2.获取用户数据列表 List<User> list = new ArrayList<>(); System.out.println(sheet.getLastRowNum()); for (int rowNum = 1; rowNum<= sheet.getLastRowNum() ;rowNum ++) { Row row = sheet.getRow(rowNum);//根据索引获取每一个行 Object [] values = new Object[row.getLastCellNum()]; for(int cellNum=1;cellNum< row.getLastCellNum(); cellNum ++) { Cell cell = row.getCell(cellNum); Object value = getCellValue(cell); values[cellNum] = value; } User user = new User(values); list.add(user); } //3.批量保存用户 userService.saveAll(list,companyId,companyName); return new Result(ResultCode.SUCCESS); } public void saveAll(List<User> list ,String companyId,String companyName){ for (User user : list) { //默认密码 user.setPassword(new Md5Hash("123456",user.getMobile(),3).toString()); //id user.setId(idWorker.nextId()+""); //基本属性 user.setCompanyId(companyId); user.setCompanyName(companyName); user.setInServiceStatus(1); user.setEnableState(1); user.setLevel("user"); //填充部门的属性 Department department = departmentFeignClient.findByCode(user.getDepartmentId(), companyId); if(department != null) { user.setDepartmentId(department.getId()); user.setDepartmentName(department.getName()); } userDao.save(user); } } /** * 1.保存用户 */ public void save(User user) { //设置主键的值 String id = idWorker.nextId()+""; String password = new Md5Hash("123456",user.getMobile(),3).toString(); user.setLevel("user"); user.setPassword(password);//设置初始密码 user.setEnableState(1); user.setId(id); //调用dao保存部门 userDao.save(user); } public static Object getCellValue(Cell cell) { //1.获取到单元格的属性类型 CellType cellType = cell.getCellType(); //2.根据单元格数据类型获取数据 Object value = null; switch (cellType) { case STRING: value = cell.getStringCellValue(); break; case BOOLEAN: value = cell.getBooleanCellValue(); break; case NUMERIC: if(DateUtil.isCellDateFormatted(cell)) { //日期格式 value = cell.getDateCellValue(); }else{ //数字 value = cell.getNumericCellValue(); } break; case FORMULA: //公式 value = cell.getCellFormula(); break; default: break; } return value; }
手把手视频详细讲解项目开发全过程,需要的小伙伴自行百度网盘下载,链接见附件,永久有效。 项目介绍: iHRM是一款基于SaaS平台的人力资源管理系统, 企业通过该系统可以完成员工管理、审批管理、考勤管理、社保公积金管理、薪资管理等功能,为企业的人力资源管理提供一站式解决方案。 掌握的核心能力:   1、能够了解SaaS的基本概念   2、掌握Activiti7工作流引擎的使用   3、能够掌握商用权限方案的设计   4、能够使用JasperReport生成报表。   5、能够使用PowerDesigner构建数据库模型   6、了解SAAS-HRM中权限控制   7、理解前端权限控制思路   8、熟练构造Chart图形报表 解决方法:   1、Spring全家桶解决方案|   2、SPA工程构建解决方案|   3、Saas系统数据库设计方案|   4、统一会话管理的解决方案|   5、企业级报表解决方案|   6、系统认证授权的解决方案|   7、云存储解决方案|   8、RBAC权限设计方案|   9、刷脸登录解决方案|   10、自定义代码生成器|   11、Activiti工作流开发| 涵盖知识点:   1.结合Activiti7工作流引擎的应用教程。   2.基于Shiro+Redis的分布式session解决方案。   3.可商用的权限设计方案(提供菜单,按钮,超链接,API粒度的权限控制)。   4.完整的代码生成器教程。   5.采用JasperReport完成企业级PDF报表生成。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我爱布朗熊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值