数据处理 --- 枚举

267 阅读4分钟

bgc-05.jpeg

前言

最近的项目中需求需要将表格数据导入导出,基于vue-element-admin有这个组件功能外,我们还要做一些简单的数据格式化处理

分析

表格中除了简单的添加功能,有时管理一次性需要导入导出多份数据,这个样子一次次添加是很麻烦的,需求就产生了

  • 实现 1,后端处理:前端只需要将excel数据上传,后端接受业务做数据处理

2,前端处理:

注意:这个 Excel 文件不是用户想传什么就传什么的, Excel 文件格式、字段是提前定义好的,用户需要按照格式、字段填充数据,进行上传

前端需要做的就是数据格式化好再上传或者接收,Excel 的导入导出都是依赖于js-xlsx插件来实现的,在 js-xlsx的基础上又封装了Export2Excel.js来方便导出数据

  • vue-element-admin 先分析下人家的源码
<upload-excel-component :on-success="handleSuccess" :before-upload="beforeUpload" />

这个是人家封装好的组件,其中两个钩子是on-success:上传成功,在里面执行上传成功以后的逻辑处理,before-upload:上传之前进行验证、文件格式、文件的大小等

用户点击按钮后,触发的实际是**input隐藏域**click事件,当上传文件后,触发隐藏域的change事件后

handleClick(e) {
      console.log(e)
      // 通过事件对象获取到上传的文件信息
      const files = e.target.files
      // 获取到上传的文件
      const rawFile = files[0] // only use files[0]
      // 开始判断是否选择了文件
      if (!rawFile) return
      this.upload(rawFile)
    }

通过事件对象获取到上传的文件,这里还不能直接做数据处理,需要嵌套调用来判断上传的文件符不符合规范,比如文件大小,格式等

upload(rawFile) {
      this.$refs['excel-upload-input'].value = null // fix can't select the same excel

      // beforeUpload:是父级传递方法,进行上传之前逻辑的处理
      // 例如:判断文件格式是否正确、判断文件大小
      if (!this.beforeUpload) {
        this.readerData(rawFile)
        return
      }
      // 父级开始进行逻辑处理,返回 true 或者 false
      const before = this.beforeUpload(rawFile)

      // 如果返回 true,说明逻辑通过
      if (before) {
        this.readerData(rawFile)
      }
    }

接着通过xlsx插件的方法读取文件处理成我们需要的表头和表格数据体

generateData({ header, results }) {
      // 接收 表头 和 具体的数据,赋值给 data 中的状态
      this.excelData.header = header
      this.excelData.results = results

      // 开始判断父级是否传递了 onSuccess 事件,如果父级传递了事件,开始将 表头 和 具体的数据 传递给父级
      this.onSuccess && this.onSuccess(this.excelData)
    }

以上是在官网上粘贴,有兴趣的可以去官网阅读gitee.com/julywind/vu…

枚举数据处理

  • 导入 此处就以自己的项目为例了,通过插件处理后的数据如下

表头:['姓名', '手机号', '入职日期', '转正日期', '工号', '部门']

数据体:

[

{入职时间:45166,姓名:'阿克尚',工号:'1001',手机号:'13333333333',转正日期:46123,部门:'艾欧尼亚'}

...

]

// 格式化results
  function transExcel(results) {
      // 定义原始枚举对象
      const userRelations = {
        '入职日期': 'timeOfEntry',
        '手机号': 'mobile',
        '姓名': 'username',
        '转正日期': 'correctionTime',
        '工号': 'workNumber',
        '部门': 'departmentName',
        '聘用形式': 'formOfEmployment'
      }

      return results.map(item => {
        const obj = {}
        // 得到原数组中每一项对象的key组成的数组
        const transKey = Object.keys(item)
        // 遍历数组枚举得到obj的key
        transKey.forEach(key => {
          const objKey = userRelations[key]
          // 判断值是否为转正和入职时间转换为时间戳
          if (objKey === 'timeOfEntry' || objKey === 'correctionTime') {
            obj[objKey] = new Date(formatExcelDate(item[key])) // 这里是表格事件转时间戳的一个方法
          } else {
            // 当前每一项的值赋值给obj的值
            obj[objKey] = item[key]
          }
        })

        return obj
      })
    }

` 返回符合后端格式数据

  • 导出 导出除了xlsx还基于Export2Excel.js
import('@/vendor/Export2Excel').then(excel => {
  excel.export_json_to_excel({
    header: tHeader, //表头 必填
    data, //具体数据 必填
    filename: 'excel-list', //非必填
    autoWidth: true, //非必填
    bookType: 'xlsx' //非必填
  })
})
function transData(data) {
      // 准备枚举的对象
      const map = {
        'id': '编号',
        'password': '密码',
        'mobile': '手机号',
        'username': '姓名',
        'timeOfEntry': '入职日期',
        'formOfEmployment': '聘用形式',
        'correctionTime': '转正日期',
        'workNumber': '工号',
        'departmentName': '部门',
        'staffPhoto': '头像地址'
      }
      const headerKey = Object.keys(data[0])
      const headers = headerKey.map(item => {
        return map[item]
      })
      const results = data.map(item => {
        return Object.values(item)
      })
      return { headers, results }
    }

上面提到的时间处理这里补充下 1、excel的日期是以1900-1-0开始计算的 2、js的Date是以 1970-1-1 08:00:00 开始的

function formatExcelDate(numb, format = '/') {
  const time = new Date((numb - 25567) * 24 * 3600000 - 5 * 60 * 1000 - 43 * 1000 - 24 * 3600000 - 8 * 3600000)
  time.setYear(time.getFullYear())
  const year = time.getFullYear() + ''
  const month = time.getMonth() + 1 + ''
  const date = time.getDate() + ''
  if (format && format.length === 1) {
    return year + format + month + format + date
  }
  return year + (month < 10 ? '0' + month : month) + (date < 10 ? '0' + date : date)
}

通过枚举一一对应的关系,我们顺利的数据转换,方便调用API

结语

写的不好,有错误的地方烦请各位大佬多多指教,感恩家人感恩🙏 🚩祝各位一路顺风,顶峰相见