天天看點

vue 導入 - element - xlsx

前言

星期五,又可以熬夜了,嘻嘻嘻,當然我說的是熬夜學習,把最近項目中的導入拿了出來,寫了一個小Demo,友善大家直接使用

導入總結

說起導入,很多的背景管理裡面都有,******什麼一鍵導入,一鍵導出啊。可憐的開發仔,小醜竟是我自己

話不多說,先看電視

  • 項目業務:導入存本地,導出從本地拿
vue 導入 - element - xlsx

這裡用到了

element

的上傳元件,如果你也是,直接拿走

導出看下集<<<<<<<<<<

安裝

npm install xlsx
           

上傳的頁面,如果你使用的是 element 的直接拷貝,小白可以看有每一步的注釋

<template>
  <div class="uploadBox">
    <!-- 傳回首頁 -->
    <div class="homeBox">
      <router-link to="/">
        <el-tooltip content="傳回清單頁面" placement="top">
          <i class="el-icon-tickets"></i>
        </el-tooltip>
      </router-link>
    </div>

    <!-- 上傳檔案按鈕 -->
    <div class="buttonBox">
      <el-upload
        action
        accept=".xlsx,.xls"
        :auto-upload="false"
        :show-file-list="false"
        :on-change="handle"
      >
        <el-button type="primary" slot="trigger">選取 Excel 檔案</el-button>
      </el-upload>
      <el-button type="success" @click="submit">采集資料送出</el-button>
    </div>

    <!-- 解析出來的資料 -->
    <div class="tableBox" v-show="show">
      <h3>
        <i class="el-icon-info">
          小主,以下是采集完成的資料,請您檢查無誤後,點選“采集資料送出”按鈕上傳至伺服器</i
        >
      </h3>
      <el-table :data="tempData" border style="width: 100%" :height="height">
        <el-table-column
          prop="name"
          label="姓名"
          min-width="50%"
        ></el-table-column>
        <el-table-column
          prop="phone"
          label="電話"
          min-width="50%"
        ></el-table-column>
      </el-table>
    </div>
  </div>
</template>

<script>
import xlsx from 'xlsx' // 需要安裝的導入插件
import { Loading } from 'element-ui' // element的loading 服務
import { readFile, character, delay } from '../assets/js/utils' // 封裝的方法 必看
export default {
  name: 'Upload',
  data() {
    return {
      height: document.documentElement.clientHeight - 130,
      tempData: [], // 表格資料
      show: false // 表格是否顯示
    }
  },
  methods: {
    // 采集 EXCEL 資料
    async handle(e) {
      let file = e.raw // 拿到 File 對象
      if (!file) return // 沒有就不往下走

      this.show = false // 沒次進來,表格先不顯示
      let loading = Loading.service({ // 提前定義一個 element的一個異步loading服務
        text: '小主,請您稍等片刻,女家正在玩命進行中...',
        background: 'rgba(0,0,0,.5)'
      })

      await delay(300) // 調用的外部方法,看下面,作用是人性化等待300毫秒,代碼再像下走

      // 讀取FILE中的資料
      let data = await readFile(file) // 調用的外部方法,二進制讀取表格裡的資料
      // 打開xlsx檔案,最下面是你打開的哪一個表卡
      let workbook = xlsx.read(data, { type: 'binary' }), // 利用xlsx的内置方法得到讀取到所有的表卡的xlsx資料
        worksheet = workbook.Sheets[workbook.SheetNames[0]], // 拿到你第一個
        list = xlsx.utils.sheet_to_json(worksheet) // xlsx轉換成JSON格式 順便給空的單元格指派為空字元串
      // console.log(list)

      // 把讀取出來的資料變為可以送出為伺服器的資料格式
      let arr = [] // 定義一個空數組
      let oldData = JSON.parse(window.localStorage.getItem('excel') || '[]') // 檢視本地的excel
      let index = oldData.length // 指派一個index索引
      list.forEach(item => { // 循環上面拿到的表格資料
        let obj = {} // 定義一個對象,一會給顯示表單當資料
        for (let key in character) { // 别問從哪來的,看引入的方法
          if (!character.hasOwnProperty(key)) break // 根據 key去重
          let v = character[key], // 下面這是改變讀取到表單的名字(剛看有點,不防自己修改方法裡的對象列印一下)
            text = v.text,
            type = v.type
          v = item[text] || ''
          type === 'string' ? (v = String(v)) : null // 給不同的資料定義類型
          type === 'number' ? (v = Number(v)) : null
          obj[key] = v // 給對象裡的Key指派
        }
        obj.id = ++index // id 索引加加
        obj.time = new Date() // new一個時間給每一個對象,可能你們用不到
        arr.push(obj) // arr 就是給後端的資料
      })

      await delay(300) // 讓時間靜止300毫秒,體驗感爆棚

      // 展示到頁面中
      this.show = true // 此時已經改整理好的資料準備好了,讓傳遞給後端的表格顯示把,可以檢查資料對不對
      console.log(arr,'這就是傳給後端的資料')
      this.tempData = arr // 給表格指派
      loading.close() // loading的服務也可以關了
    },
    // 送出資料給伺服器
    submit() {
      if (this.tempData.length <= 0) { // 如果沒有上傳東西
        return this.$message({ // 提示
          message: '小主,請您先選擇 EXCEL 檔案!',
          type: 'warning',
          showClose: true
        })
      }
      // 存到本地,為下節導入導出做準備 在實際項目中這裡就是給後端傳資料的接口了
      let oldData = JSON.parse(window.localStorage.getItem('excel') || '[]'), // 深拷貝
        newData = [...oldData, ...this.tempData] // 結構
      window.localStorage.setItem('excel', JSON.stringify(newData)) // 存到本地,為下節導入導出做準備
      this.$message({
        message: '檔案已儲存到本地!',
        type: 'success',
        showClose: true
      })
    }
  }
}
</script>

<style lang="less" scoped>
.homeBox {
  position: fixed;
  top: 10px;
  right: 20px;
  z-index: 9999;
  font-size: 40px;
}

.buttonBox {
  padding: 15px;
  display: flex;
  width: 35%;
  justify-content: flex-start;
  & .el-button {
    margin-right: 20px !important;
  }
}

.tableBox {
  padding: 0 15px;
  h3 {
    font-size: 18px;
    color: #f56c6c;
    padding-bottom: 15px;
  }
}
</style>

           

引入的三個方法的檔案

// 設定異步延遲間隔
export function delay(interval = 0) {
  return new Promise(resolve => {
    let timer = setTimeout(_ => {
      clearTimeout(timer)
      resolve()
    }, interval)
  })
}

// 按照二進制讀取檔案
export function readFile(file) {
  return new Promise(resolve => {
    let reader = new FileReader()
    reader.readAsBinaryString(file)
    reader.onload = e => {
      resolve(e.target.result)
    }
  })
}

// 字段對應表
export let character = { // 根據實際情況,添加表頭資訊,類型
  name: {
    text: '姓名',
    type: 'string'
  },
  phone: {
    text: '電話',
    type: 'string'
  }
}

// 時間字元串格式化
export function formatTime(str, tpl) {
  let arr = str.match(/\d+/g).map(item => {
    return item.length < 2 ? '0' + item : item
  })
  tpl = tpl || '{0}年{1}月{2}日 {3}時{4}分{5}秒'
  return tpl.replace(/\{(\d+)\}/g, (_, group) => {
    return arr[group] || '00'
  })
}

           

有需要源碼的,call 我…

繼續閱讀