1. 程式人生 > 其它 >vue匯入,匯出,列表展示excel資料

vue匯入,匯出,列表展示excel資料

 1 <template>
 2   <div class="index" v-loading.fullscreen.lock="fullscreenLoading" element-loading-text="拼命載入中...">
 3     <input type="file" @change="importFile(this)" id="imFile" style="display: none"
 4            accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel
"/> 5 <a id="downlink"></a> 6 <el-button class="button" @click="uploadFile()">匯入</el-button> 7 <el-button class="button" @click="downloadFile(list)">匯出</el-button> 8 <el-select 9 v-model="search" 10 multiple 11 filterable 12
placeholder="請輸入關鍵詞" 13 :loading="loading"> 14 <el-option 15 v-for="item in list" 16 :key="item.id" 17 :label="item.name" 18 :value="item.id"> 19 </el-option> 20 </el-select> 21 <!--錯誤資訊提示--> 22 <el-dialog title="
提示" v-model="errorDialog" size="tiny"> 23 <span>{{errorMsg}}</span> 24 <span slot="footer" class="dialog-footer"> 25 <el-button type="primary" @click="errorDialog=false">確認</el-button> 26 </span> 27 28 </el-dialog> 29 <!--展示匯入資訊--> 30 <el-table :data="listClone" tooltip-effect="dark"> 31 <el-table-column label="名稱" prop="name" show-overflow-tooltip></el-table-column> 32 <el-table-column label="請求方法" prop="method" show-overflow-tooltip></el-table-column> 33 <el-table-column label="路徑" prop="path" show-overflow-tooltip></el-table-column> 34 <el-table-column label="所屬專案" prop="project.name" show-overflow-tooltip></el-table-column> 35 <el-table-column label="建立時間" prop="created_at" show-overflow-tooltip></el-table-column> 36 <el-table-column label="操作" show-overflow-tooltip> 37 <el-link icon="el-icon-edit" @click="dialog = true">編輯</el-link> 38 <!-- 側邊欄修改專案 --> 39 <!-- 彈出框,新增,編輯 --> 40 <el-drawer 41 title="修改" 42 :before-close="handleClose" 43 :visible.sync="dialog" 44 direction="ltr" 45 custom-class="demo-drawer" 46 @click="handleUpdate(row)" 47 ref="drawer" 48 size="55%" 49 > 50 <Interface></Interface> 51 </el-drawer> 52 </el-table-column> 53 </el-table> 54 <!-- 分頁 --> 55 <pagination 56 v-show="total > 0" 57 :total="total" 58 :page.sync="queryInfo.page" 59 :limit.sync="queryInfo.limit" 60 @pagination="getList" 61 /> 62 </div> 63 </template>
<script>
  import {
    fetchList,
    projectList,
    fetchName,
  } from '/api/case'
  import service from "../../utils/axios";
  import Interface from "../../components/interface";
  // import Pagination from "../../components/Pagination"
  // 引入xlsx
  var XLSX = require('xlsx')
  export default {
    name: 'info',
    components: {Interface,},
    data() {
      return {
        total: 0,
        search: [],
        value: [],
        loading: false,
        timeout: null,
        dialog: false,
        filter: '',
        fullscreenLoading: false, // 載入中
        imFile: '', // 匯入檔案el
        outFile: '',  // 匯出檔案el
        errorDialog: false, // 錯誤資訊彈窗
        errorMsg: '', // 錯誤資訊內容
        list: [], // 返回資料
        listClone: [],
        queryInfo: {
          page: 1,
          limit: 20,
          name: ''
        },
        dialogStatus: '',
        textMap: {
          update: '編輯',
          create: '建立'
        },
   
        formLabelWidth: '80px',
        timer: null,
      }
    },
    mounted() {
      this.imFile = document.getElementById('imFile')
      this.outFile = document.getElementById('downlink')
      this.list = this.list.map(item => {
        return {value: `value:${item}`, label: `label:${item}`};
      });
    },
    watch: {
      search: {
        handler(val) {
          this.listClone = val.length ? this.list.filter((e) => val.find((item) => item === e.id)) : this.list;
        },
        deep: true,
        immediate: true,
      },
    },
    created() {
      this.getList()
    },
    methods: {

      /* 篩選 */
      nameList() {
        fetchName(this.queryInfo).then((service) => {
          this.list = service.data.data.items
        })
      },

      /* 修改資料 */
      handleUpdate() {
        projectList().then((res) => (this.projects = res.data.items))
        this.list = Object.assign({}, row) // copy obj
        this.dialogStatus = 'update'
        this.$nextTick(() => {
          this.$refs['dataForm'].clearValidate()
        })
      },

      /* 獲取list資料 */
      getList() {
        this.listLoading = true
        fetchList(this.queryInfo).then((service) => {
          this.list = service.data.data.items
          this.listClone = this.list;
          this.total = service.data.data.total

          // Just to simulate the time of the request
          setTimeout(() => {
            this.listLoading = false
          }, 1.5 * 1000)
        })
      },

      /*  匯入按鈕  */
      uploadFile: function () { // 點選匯入按鈕
        this.imFile.click()
      },

      /* 匯出  */
      downloadFile: function (rs) { // 點選匯出按鈕
        let data = [{}]
        for (let k in rs[0]) {
          data[0][k] = k
        }
        data = data.concat(rs)
        this.downloadExl(data, 'test用例')
      },

      /* 匯入execl */
      importFile: function () { // 匯入excel
        this.fullscreenLoading = true
        let obj = this.imFile
        if (!obj.files) {
          this.fullscreenLoading = false
          return
        }
        var f = obj.files[0]
        var reader = new FileReader()
        let $t = this
        reader.onload = function (e) {
          var data = e.target.result
          if ($t.rABS) {
            $t.wb = XLSX.read(btoa(this.fixdata(data)), {  // 手動轉化
              type: 'base64'
            })
          } else {
            $t.wb = XLSX.read(data, {
              type: 'binary'
            })
          }
          let json = XLSX.utils.sheet_to_json($t.wb.Sheets[$t.wb.SheetNames[0]])
          console.log(typeof json)
          $t.dealFile($t.analyzeData(json)) // analyzeData: 解析匯入資料
        }
        if (this.rABS) {
          reader.readAsArrayBuffer(f)
        } else {
          reader.readAsBinaryString(f)
        }
      },

      /* 匯出execl  */
      downloadExl: function (json, downName, type) {  // 匯出到excel
        let keyMap = [] // 獲取鍵
        for (let k in json[0]) {
          keyMap.push(k)
        }
        console.info('keyMap', keyMap, json)
        let tmpdata = [] // 用來儲存轉換好的json
        json.map((v, i) => keyMap.map((k, j) => Object.assign({}, {
          v: v[k],
          position: (j > 25 ? this.getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1)
        }))).reduce((prev, next) => prev.concat(next)).forEach(function (v) {
          tmpdata[v.position] = {
            v: v.v
          }
        })
        let outputPos = Object.keys(tmpdata)  // 設定區域,比如表格從A1到D10
        let tmpWB = {
          SheetNames: ['mySheet'], // 儲存的表標題
          Sheets: {
            'mySheet': Object.assign({},
              tmpdata, // 內容
              {
                '!ref': outputPos[0] + ':' + outputPos[outputPos.length - 1] // 設定填充區域
              })
          }
        }
        let tmpDown = new Blob([this.s2ab(XLSX.write(tmpWB,
          {bookType: (type === undefined ? 'xlsx' : type), bookSST: false, type: 'binary'} // 這裡的資料是用來定義匯出的格式型別
        ))], {
          type: ''
        })  // 建立二進位制物件寫入轉換好的位元組流
        var href = URL.createObjectURL(tmpDown)  // 建立物件超連結
        this.outFile.download = downName + '.xlsx'  // 下載名稱
        this.outFile.href = href  // 繫結a標籤
        this.outFile.click()  // 模擬點選實現下載
        setTimeout(function () {  // 延時釋放
          URL.revokeObjectURL(tmpDown) // 用URL.revokeObjectURL()來釋放這個object URL
        }, 100)
      },

      /* 解析資料  */
      analyzeData: function (data) {  // 此處可以解析匯入資料
        return data
      },

      /* 處理匯入資料 */
      dealFile: function (data) {   // 處理匯入的資料
        console.log(data)
        this.imFile.value = ''
        this.fullscreenLoading = false
        if (data.length <= 0) {
          this.errorDialog = true
          this.errorMsg = '請匯入正確資訊'
        } else {
          this.listClone = data
        }
      },
      s2ab: function (s) { // 字串轉字元流
        var buf = new ArrayBuffer(s.length)
        var view = new Uint8Array(buf)
        for (var i = 0; i !== s.length; ++i) {
          view[i] = s.charCodeAt(i) & 0xFF
        }
        return buf
      },
      getCharCol: function (n) { // 將指定的自然數轉換為26進製表示。對映關係:[0-25] -> [A-Z]。
        let s = ''
        let m = 0
        while (n > 0) {
          m = n % 26 + 1
          s = String.fromCharCode(m + 64) + s
          n = (n - m) / 26
        }
        return s
      },
      fixdata: function (data) {  // 檔案流轉BinaryString
        var o = ''
        var l = 0
        var w = 10240
        for (; l < data.byteLength / w; ++l) {
          o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w, l * w + w)))
        }
        o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)))
        return o
      },
      handleClose(done) {
        if (this.loading) {
          return;
        }
        this.$confirm('確定要提交表單嗎?')
          .then(_ => {
            this.loading = true;
            this.timer = setTimeout(() => {
              done();
              // 動畫關閉需要一定的時間
              setTimeout(() => {
                this.loading = false;
              }, 10);
            }, 10);
          })
          .catch(_ => {
          });
      },
    }
  }
</script>
  • 匯出表格

  • 列表展示