vue 導入excel數據組件

1.組件,導入數據,必定要先下載模版,而後點擊導入數據,會提示導入成功條數,失敗條數css

<template>
  <div class="excel" >
    <el-dialog
      :visible.sync="centerDialogVisible"
      :title="titleName"
      :close-on-click-modal="false"
      :before-close="beforePausClose"
      width="1040px"
    >
      <div style="min-height: 550px;padding: 0 20px">
        <div class="excel-header">
          <el-select v-show="templateShow" v-model="value" placeholder="請選擇導入的模板" @change="changeTemplate($event)">
            <el-option
              v-for="item in options"
              :key="item.template_table_name"
              :label="item.template_description"
              :value="item.template_table_name"/>
          </el-select>
          <el-button :disabled="selectPower" class="diybut" @click="btnClick">選擇Excel文件</el-button>
          <el-button :disabled="exportBtn" class="diybut" @click="exportExcel">下載模板</el-button>
          <el-checkbox v-show="checkBoxMutiplian" v-model="picSubmitShow">將圖片保存到系統中</el-checkbox>
          <div style="margin: 0 auto;display: inline-block;float: right">
            <el-button :disabled="exportPower" class="diybut" @click="saveDataBase">導入</el-button>
            <el-button :disabled="canclePower" class="diybut" @click="cancleTemplate">關閉</el-button>
          </div>
        </div>
        <div v-show="errorPromptShow" class="error-prompt" style="max-height: 100px;overflow-y: auto">
          <p v-for="(item, index) in errorList" :key="index" style="color: red;height: 20px;line-height: 14px;margin: 0">
            {{ item }}
          </p>
        </div>
        <!--        手動編寫的滾動條-->
        <div v-show="progressDebugShow" style="width: 100%;height: 20px;background: #4FA6E0;position: relative;border-radius: 5px;line-height: 20px;margin-bottom: 20px;overflow: hidden">
          <div class="slider" style=" position:absolute;left: 10px;top: 1px;">
            <div style="width: 10px;height: 10px;line-height: 10px;border-radius: 5px;background: white;display: inline-block" />
            <div style="width: 10px;height: 10px;line-height: 10px;border-radius: 5px;background: white;display: inline-block" />
            <div style="width: 10px;height: 10px;line-height: 10px;border-radius: 5px;background: white;display: inline-block" />
          </div>
        </div>
        <div>
          <p v-show="resultShow" style="height: 30px;line-height: 30px;margin-top: 10px">
            <span>成功:{{ successCount }}條</span>
            <span style="margin: 0 20px">失敗:{{ failCount }}條</span>
            <el-button v-show="failCount !== 0" type="text" @click="exportFailData">下載導入失敗數據</el-button>
          </p>
        </div>
        <!--       表格-->
        <div
          v-loading="loading"
          style="width:100%;overflow-x: auto;min-height: 425px"
          element-loading-text="保存中,請稍等"
          element-loading-spinner="el-icon-loading">
          <table
            border="1px solid gray"
            style="border-collapse: collapse;width: 960px"
          >
            <!--顯示數據庫查出來的標題-->
            <tr style="text-align: center;height: 30px;line-height: 0;width: 1000px;background: #F4F4F4">
              <td v-for="(item ,index) in arr" :key="index" style=" height: 40px;">
                <div class="tableWidth" style="min-width: 100px;white-space:nowrap;">
                  <span v-show="templateAllData[index].attribute_not_null" style="color: red">*</span>{{ item }}
                  <input v-show="picSubmitShow" ref="mutiCheck" :value="item" v-model="checked" type="checkbox" style="margin-left: 10px;display: inline-block;position: relative;top: 3px">
                </div>
              </td>
            </tr>
            <!--從excel中獲取的標題-->
            <tr style="height: 40px;overflow: hidden;line-height: 0">
              <td v-for="(item ,index) in arr" :key="index" style="width: 30px;white-space:nowrap;">
                <select v-model="changeList[item]" :value="item" class="selectedList" @change="changeListValue(index)">
                  <option v-for="(item1, index1) in arr1" :key="index1" :value="item1" >
                    {{ item1 }}
                  </option>
                </select>
              </td>
            </tr>
            <!--excel中獲取的具體數據展現-->
            <tr v-for="(item, index) in tableData" :key="index">
              <td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;">
                <div :title="item[item1]" style="width: 150px;white-space:nowrap;overflow: hidden;line-height: 2;height: 20px">
                  {{ item[item1] }}
                </div>
              </td>
            </tr>
            <tr v-show="tableShow" class="tableShow">
              <td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
            </tr>
            <tr v-show="tableShow" class="tableShow">
              <td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
            </tr>
            <tr v-show="tableShow" class="tableShow">
              <td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
            </tr>
            <tr v-show="tableShow" class="tableShow">
              <td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
            </tr>
            <tr v-show="tableShow" class="tableShow">
              <td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
            </tr>
            <tr v-show="tableShow" class="tableShow">
              <td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
            </tr>
            <tr v-show="tableShow" class="tableShow">
              <td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
            </tr>
            <tr v-show="tableShow" class="tableShow">
              <td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
            </tr>
            <tr v-show="tableShow" class="tableShow">
              <td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
            </tr>
            <tr v-show="tableShow" class="tableShow">
              <td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
            </tr>

          </table>
        </div>
        <p style="text-align: center;line-height: 50px;margin-bottom: 0">(預覽數據)</p>
      </div>
    </el-dialog>
    <input
      accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
      class="input-file"
      type="file"
      @change="exportData"
    >
    <el-button
      :type="buttonType"
      :disabled="disabled"
      :icon="buttonIcon"
      :size="buttonSize"
      @click="getAllTemplateData">
      {{ titleName }}
    </el-button>
    <el-dialog
      :visible.sync="centerDialogVisibleTwo"
      title="導入結果"
      width="40%"
      center>
      <p style="text-align: center">成功條數:{{ successCount }}</p>
      <p style="text-align: center">失敗條數:{{ failCount }}</p>
      <span slot="footer" class="dialog-footer">
        <el-button @click="centerDialogVisibleTwo = false">關閉</el-button>
        <el-button v-show="exportFale" type="primary" @click="exportFailData">導出失敗數據</el-button>
      </span>
    </el-dialog>

  </div>
</template>

<script>
import { getTemplate, getTemplateHeader, saveExcel, uploadPicToQn, getFailData } from '@/api/excel'
import XLSX from 'xlsx'
import { mapGetters } from 'vuex'
import $ from 'jquery'
export default {
  props: {
    disabled: {
      type: Boolean,
      default: false // 是否有禁用權限
    },
    titleName: {
      type: String,
      default: '批量導入商品信息' //  傳入不一樣的標題
    },
    actionName: {
      type: String,
      default: 'commodity' // commodity商品,commodity_specification商品規格,sales_team,銷售組 customer_department 客戶單位 customer客戶   根據不一樣使用傳入不一樣的數據
    },
    buttonType: {
      type: String,
      default: '' // 控制Button的類型
    },
    buttonIcon: {
      type: String,
      default: '' // 控制Button中的圖標 (僅支持element-ui中自帶圖標)
    },
    buttonSize: {
      type: String,
      default: '' // 控制Button的尺寸
    }
  },
  data() {
    return {
      arr: [], // 放從數據庫獲取的標題
      arr1: [], // 導入的excel中的標題
      tableData: [], // 用於循環展現的值
      copyTableData: [], // 用於保存最初的json數據。以便進行數據更換
      changeList: {}, // 動態綁定下拉框的值
      submitLastValue: [], // 最終提交的值
      centerDialogVisible: false, // 對話框1顯示
      centerDialogVisibleTwo: false, // 對話框2顯示
      options: [], // 模板列表
      value: '', // 選擇的模板值
      templateAllData: [],
      checked: [], // 用於圖片轉換的輸入框列表
      debugCount: 0,
      copyTableDataTwo: [], // 用於下拉框切換時的數據展現
      picSubmitShow: false, // 是否顯示圖片轉換輸入框
      template: [],
      oneArr: 0, // 用於在圖片轉換時判斷是否轉換完成
      twoArr: 0, // 用於在圖片轉換時判斷是否轉換完成
      count: 0,
      loading: false, // 加載圖標
      successCount: 0, // 成功條數
      failCount: 0, // 失敗條數
      exportBtn: true, // 導入按鈕權限
      exportFale: true, // 用於判斷是否導出失敗數據
      templateShow: true,
      checkBoxMutiplian: false,
      progressTimer: '',
      errorList: [], // 前端校驗錯誤提示
      progress: 0, // 進度條百分比
      progressDebugShow: false, // 滾動條是否顯示
      errorPromptShow: false, // 校驗失敗提示是否顯示
      resultShow: false, // 控制導入結果顯示
      selectPower: false, // 選擇模板權限
      exportPower: false, // 導入按鈕權限
      canclePower: false, // 關閉按鈕權限
      iconClickPower: 0, // 控制點擊對話框關閉圖標是否執行
      tableShow: true // 顯示空表格
    }
  },
  computed: {
    ...mapGetters([
      'business_group_id'
    ])
  },
  watch: {
    debugCount: function(newV, oldV) {
      // if (newV === this.submitLastValue.length * this.checked.length) {
      //   this.saveResult()
      // }
    },
    twoArr: function(newV, oldV) {
      if (this.checked.length > 0) {
        setTimeout(this.PicTransfer, 100)
      }
    },
    tableData: function(newV, oldV) {
      // if (this.tableData.length > 0) {
      //   this.tableShow = false
      // } else {
      //   this.tableShow = true
      // }
    }
  },
  beforeDestroy() {
    clearInterval(this.progressTimer)
  },
  methods: {
    getAllTemplateData: function() {
      this.arr1 = []
      this.arr = []
      this.value = ''
      this.tableData = []
      this.copyTableDataTwo = []
      this.copyTableData = []
      this.centerDialogVisible = true
      this.progressDebugShow = false
      this.resultShow = false
      this.count = 0
      this.oneArr = 0
      this.twoArr = 0
      this.checked = []
      this.picSubmitShow = false
      this.getDefaultArr()
    },
    // 獲取數據庫模板數據
    getDefaultArr: function() {
      let group_id = ''
      if (this.actionName === 'commodity') {
        group_id = this.business_group_id
      }
      getTemplate(group_id, this.actionName)
        .then(res => {
          this.options = res.data
          if (this.options.length === 1) {
            this.value = this.options[0].template_table_name
            this.templateShow = false
            this.changeTemplate(this.value)
          }
        })
        .catch(() => {})
    },
    // 點擊對話框的X圖標事件
    beforePausClose() {
      if (this.iconClickPower === 1) {
        return
      } else {
        this.centerDialogVisible = false
      }
    },
    // 取消
    cancleTemplate: function() {
      this.value = ''
      this.arr = []
      this.arr1 = []
      this.value = ''
      this.tableData = []
      this.centerDialogVisible = false
      this.centerDialogVisibleTwo = false
      this.exportBtn = true
      clearInterval(this.progressTimer)
      document.querySelector('.input-file').value = ''
    },
    // 切換模板時
    changeTemplate: function(data) {
      if (data !== '') {
        this.arr = []
        getTemplateHeader(data)
          .then(res => {
            this.templateAllData = res.data.data
            this.checkBoxMutiplian = res.data.need_save_pictures
            this.template = []
            const obj = {}
            res.data.data.forEach((item, index) => {
              obj[item.attribute_name] = ''
              this.arr.push(item.attribute_name)
            })
            this.template.push(obj)
            this.exportBtn = false
            // 動態添加changeList的值
            for (let i = 0; i < this.arr.length; i++) {
              this.changeList[this.arr[i]] = this.arr[i]
            }
          })
          .catch(() => {})
      }
    },
    // 圖片轉換 將有src屬性而且爲img的值時,將src中的值改變爲後臺傳過來的值
    PicTransfer: function() {
      const a = this.submitLastValue[this.twoArr][this.checked[this.oneArr]]
      if (typeof a === 'string' && a.indexOf('<img') > -1 && a.indexOf('src') > -1) {
        const arrimg = []
        // 截取出相應的src屬性值
        a.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/gi, function(match, capture) {
          arrimg.push(capture)
        })
        uploadPicToQn(arrimg)
          .then(res => {
            for (let h = 0; h < arrimg.length; h++) {
              // this.tableData[j][this.checked[i]] = this.tableData[j][this.checked[i]].replace(arrimg[h], res.data[h].pic_name)
              this.submitLastValue[this.twoArr][this.checked[this.oneArr]] = this.submitLastValue[this.twoArr][this.checked[this.oneArr]].replace(arrimg[h], res.data[h].pic_name)
              this.count += 1
            }
            this.debugCount += 1
            if (this.oneArr === this.checked.length - 1 && this.twoArr === this.submitLastValue.length - 1) { // 判斷src的值是否轉換完成
              this.saveResult()
            } else if (this.twoArr < this.submitLastValue.length - 1) {
              this.twoArr += 1
            } else {
              this.oneArr += 1
              this.twoArr = 0
            }
          })
          .catch(() => {
            if (this.oneArr === this.checked.length - 1 && this.twoArr === this.submitLastValue.length - 1) {
              this.saveResult()
            } else if (this.twoArr < this.submitLastValue.length - 1) {
              this.twoArr += 1
            } else {
              this.oneArr += 1
              this.twoArr = 0
            }
          })
      } else {
        this.debugCount += 1
        if (this.oneArr === this.checked.length - 1 && this.twoArr === this.submitLastValue.length - 1) {
          this.saveResult()
        } else if (this.twoArr < this.submitLastValue.length - 1) {
          this.twoArr += 1
        } else {
          this.oneArr += 1
          this.twoArr = 0
        }
      }
      // this.debugCount = 0
      // for (let i = 0; i < this.checked.length; i++) {
      //   for (let j = 0; j < this.submitLastValue.length; j++) {
      //     const a = this.submitLastValue[j][this.checked[i]]
      //     if (typeof a === 'string' && a.indexOf('<img') > -1 && a.indexOf('src') > -1) {
      //       const arrimg = []
      //       // 截取出相應的src屬性值
      //       a.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/gi, function(match, capture) {
      //         arrimg.push(capture)
      //       })
      //       uploadPicToQn(arrimg)
      //         .then(res => {
      //           for (let h = 0; h < arrimg.length; h++) {
      //             // this.tableData[j][this.checked[i]] = this.tableData[j][this.checked[i]].replace(arrimg[h], res.data[h].pic_name)
      //             this.submitLastValue[j][this.checked[i]] = this.submitLastValue[j][this.checked[i]].replace(arrimg[h], res.data[h].pic_name)
      //           }
      //           this.debugCount += 1
      //           // this.resultData()
      //         })
      //         .catch(() => {})
      //     } else {
      //       this.debugCount += 1
      //     }
      //   }
      // }
    },
    btnClick() {
      if (this.value) {
        this.progressDebugShow = false
        clearInterval(this.progressTimer)
        this.resultShow = false
        document.querySelector('.input-file').click()
      } else {
        this.$message.warning('請先選擇模板')
      }
    },
    // 導入本地文件後取值
    exportData(event) {
      if (!event.currentTarget.files.length) {
        return
      }
      const that = this
      // 拿取文件對象
      const f = event.currentTarget.files[0]
      document.querySelector('.input-file').value = ''
      // 用FileReader來讀取
      const reader = new FileReader()
      // 重寫FileReader上的readAsBinaryString方法
      FileReader.prototype.readAsBinaryString = function(f) {
        let binary = ''
        let wb = '' // 讀取完成的數據
        let outdata = [] // 你須要的數據
        const reader = new FileReader()
        reader.onload = function(e) {
          // 讀取成Uint8Array,再轉換爲Unicode編碼(Unicode佔兩個字節)
          var bytes = new Uint8Array(reader.result)
          var length = bytes.byteLength
          for (let i = 0; i < length; i++) {
            binary += String.fromCharCode(bytes[i])
          }
          // 接下來就是xlsx了,具體可看api
          wb = XLSX.read(binary, {
            type: 'binary'
          })
          that.arr1 = []
          that.tableData = []
          that.copyTableDataTwo = []
          that.copyTableData = []
          outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]])
          // 獲取excel表格中的全部標題
          for (let i = 0; i < outdata.length; i++) {
            for (const j in outdata[i]) {
              let num = 0
              for (let k = 0; k < that.arr1.length; k++) {
                if (that.arr1[k] === j) {
                  num += 1
                }
              }
              if (num === 0) {
                that.arr1.push(j)
              }
            }
          }
          that.arr1.unshift(' ')
          // 字段不存在或者沒有值時,則將它的值設置爲空
          for (let i = 0; i < outdata.length; i++) {
            for (let j = 0; j < that.arr.length; j++) {
              if (!outdata[i][that.arr[j]] && outdata[i][that.arr[j]] !== 0) {
                outdata[i][that.arr[j]] = ''
              }
            }
          }
          // that.arr1 = []
          // for (const i in outdata[0]) {
          //   that.arr1.push(i)
          // }
          // console.log(outdata[0])
          // console.log(that.arr1)
          for (let i = 0; i < 10 && i < outdata.length; i++) {
            const changeValue = JSON.stringify(outdata[i])
            that.tableData.push(JSON.parse(changeValue))
            that.copyTableData.push(JSON.parse(changeValue))
          }
          // that.tableData = outdata
          // 因爲數組和對象是引用類型,在賦值時候會將地址也一塊兒賦值,當改變一個值得時候會將另一個值也改變,因此先轉爲字符串再轉回來(基本類型只會傳值不會傳地址)
          // that.copyTableData = JSON.stringify(outdata)
          that.copyTableDataTwo = JSON.stringify(outdata)
          // that.copyTableData = JSON.parse(that.copyTableData)
          that.copyTableDataTwo = JSON.parse(that.copyTableDataTwo)
          // 若是少於10行的補空格顯示十行
          $('.tableShow').removeClass('hideTr')
          if (outdata.length < 10) {
            for (let i = 0; i < outdata.length; i++) {
              $('.tableShow').eq(i).addClass('hideTr')
            }
          } else {
            $('.tableShow').addClass('hideTr')
          }
          that.resultData()
          that.centerDialogVisible = true
          // 自定義方法向父組件傳遞數據
        }
        reader.readAsArrayBuffer(f)
      }
      reader.readAsBinaryString(f)
    },
    // 下拉框的值改變後改變對應的值
    changeListValue(index) {
      // console.log(index) // 下標
      // console.log(this.arr[index])
      // console.log(this.changeList[this.arr[index]]) // 下拉框改變後的值
      for (var i = 0; i < this.tableData.length; i++) {
        this.tableData[i][this.arr[index]] = this.copyTableData[i][this.changeList[this.arr[index]]]
      }
      // console.log(this.tableData)
      this.resultData()
    },
    resultData() {
      this.submitLastValue = []
      for (let i = 0; i < this.tableData.length; i++) {
        const list = {}
        for (let j = 0; j < this.arr.length; j++) {
          if (!this.tableData[i][this.arr[j]]) {
            list[this.arr[j]] = ''
          } else {
            list[this.arr[j]] = this.tableData[i][this.arr[j]]
          }
        }
        this.submitLastValue.push(list)
      }
    },
    // 設置進度條定時器
    setTimerProgress() {
      const that = this
      clearInterval(that.progressTimer)
      that.progress = 0
      that.progressTimer = setInterval(function() {
        if (that.progress === 960) {
          that.progress = 0
        } else {
          that.progress += 3
          $('.slider').css('left', that.progress + 'px')
        }
      }, 20)
    },
    // 保存到數據庫中
    saveDataBase() {
      this.selectPower = true
      this.canclePower = true
      this.exportPower = true
      this.loading = true
      this.iconClickPower = 1
      this.submitLastValue = []
      this.resultShow = false
      this.progressDebugShow = false
      clearInterval(this.progressTimer)
      for (let j = 0; j < this.copyTableDataTwo.length; j++) {
        const obj = {}
        for (let i = 0; i < this.arr.length; i++) {
          if (this.copyTableDataTwo[j][this.changeList[this.arr[i]]] || this.copyTableDataTwo[j][this.changeList[this.arr[i]]] === 0) {
            obj[this.arr[i]] = this.copyTableDataTwo[j][this.changeList[this.arr[i]]]
          } else {
            obj[this.arr[i]] = ''
          }
        }
        this.submitLastValue.push(obj)
      }
      if (this.checked.length && this.checked.length !== 0) {
        this.PicTransfer()
      } else {
        this.saveResult()
      }
    },
    // 校驗上傳數據
    saveResult: function() {
      // 上傳數據校驗
      if (this.submitLastValue.length === 0) {
        this.$message.warning('當前暫無數據')
        this.loading = false
        this.iconClickPower = 0
        this.selectPower = false
        this.canclePower = false
        this.exportPower = false
        return
      }
      this.errorList = []
      for (let i = 0; i < this.templateAllData.length; i++) {
        for (let j = 0; j < this.submitLastValue.length; j++) {
          if (this.templateAllData[i].attribute_not_null === true && !this.submitLastValue[j][this.templateAllData[i].attribute_name] && this.submitLastValue[j][this.templateAllData[i].attribute_name] !== 0) {
            // this.$message.error(this.templateAllData[i].attribute_name + '不能爲空')
            // this.loading = false
            // return
            this.errorList.push(this.templateAllData[i].attribute_name + '不能爲空')
          }
          if ((this.templateAllData[i].attribute_not_null === 'true' || this.templateAllData[i].attribute_not_null === true) && this.templateAllData[i].attribute_type === 'int4' && (!(/(^[0-9]\d*$)/.test(this.submitLastValue[j][this.templateAllData[i].attribute_name])))) {
            // 判斷長度 this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().length > this.templateAllData[i].attribute_length
            // this.$message.error(this.templateAllData[i].attribute_name + '傳輸類型應爲整形')
            // this.loading = false
            // return
            this.errorList.push(this.templateAllData[i].attribute_name + '傳輸類型應爲整形')
          }
          if (this.templateAllData[i].attribute_type === 'numeric' && this.submitLastValue[j][this.templateAllData[i].attribute_name] && typeof this.submitLastValue[j][this.templateAllData[i].attribute_name] !== 'number') {
            // this.$message.error(this.templateAllData[i].attribute_name + '傳輸類型爲數字')
            // this.loading = false
            // return
            this.errorList.push(this.templateAllData[i].attribute_name + '傳輸類型爲數字')
          }
          if (this.templateAllData[i].attribute_type === 'date' && this.submitLastValue[j][this.templateAllData[i].attribute_name]) {
            this.submitLastValue[j][this.templateAllData[i].attribute_name] = this.submitLastValue[j][this.templateAllData[i].attribute_name].toString()
            this.submitLastValue[j][this.templateAllData[i].attribute_name] = this.submitLastValue[j][this.templateAllData[i].attribute_name].replace('年', '-')
            this.submitLastValue[j][this.templateAllData[i].attribute_name] = this.submitLastValue[j][this.templateAllData[i].attribute_name].replace('月', '-')
            this.submitLastValue[j][this.templateAllData[i].attribute_name] = this.submitLastValue[j][this.templateAllData[i].attribute_name].replace('日', '')
            if (isNaN(Date.parse(this.submitLastValue[j][this.templateAllData[i].attribute_name]))) {
              // this.$message.error(this.templateAllData[i].attribute_name + '格式有誤')
              // this.loading = false
              // return
              this.errorList.push(this.templateAllData[i].attribute_name + '格式有誤')
            }
          }
          if (this.templateAllData[i].attribute_type === 'bool') {
            if (this.submitLastValue[j][this.templateAllData[i].attribute_name] === '是' ||
              this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === 't' ||
              this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === 'true' ||
              this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === 'yes' ||
              this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === '1') {
              this.submitLastValue[j][this.templateAllData[i].attribute_name] = true
              continue
            }
            if (this.submitLastValue[j][this.templateAllData[i].attribute_name] === '否' ||
              this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === 'f' ||
              this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === 'false' ||
              this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === 'no' ||
              this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === '0') {
              this.submitLastValue[j][this.templateAllData[i].attribute_name] = false
              continue
            }
            if (this.submitLastValue[j][this.templateAllData[i].attribute_name] === '') {
              continue
            }
            // this.$message.error(this.templateAllData[i].attribute_name + '傳輸類型爲布爾值')
            // this.loading = false
            // return
            this.errorList.push(this.templateAllData[i].attribute_name + '傳輸類型爲布爾值')
          }
        }
      }
      if (this.errorList.length === 0) {
        this.progressDebugShow = true
        this.setTimerProgress()
        saveExcel(this.value, this.submitLastValue)
          .then(res => {
            this.successCount = parseInt(res.data.success)
            this.failCount = parseInt(res.data.fail)
            this.loading = false
            this.iconClickPower = 0
            this.selectPower = false
            this.canclePower = false
            this.exportPower = false
            // this.tableData = []
            // this.arr1 = []
            // this.arr = []
            // this.copyTableData = []
            // this.copyTableDataTwo = []
            // this.centerDialogVisible = false
            // this.centerDialogVisibleTwo = true
            this.resultShow = true
            clearInterval(this.progressTimer)
            this.progressDebugShow = false
            if (parseInt(this.failCount) === 0) {
              this.exportFale = false
            } else {
              this.exportFale = true
            }
            this.$emit('refleshParent') // 導入完成時在父組件刷新頁面
          })
          .catch(() => {
            this.$message({
              message: '上傳失敗',
              type: 'error',
              duration: 2 * 1000
            })
            this.loading = false
            this.iconClickPower = 0
            clearInterval(this.progressTimer)
            this.progressDebugShow = false
          })
      } else {
        // 數組去重
        const saveArr = []
        for (let i = 0; i < this.errorList.length; i++) {
          let num = 0
          for (let j = 0; j < i; j++) {
            if (this.errorList[j] === this.errorList[i]) {
              num = 1
              break
            }
          }
          if (num === 0) {
            saveArr.push(this.errorList[i])
          }
        }
        this.errorList = saveArr
        this.errorPromptShow = true
        this.loading = false
        this.iconClickPower = 0
        this.selectPower = false
        this.canclePower = false
        this.exportPower = false
      }
    },
    // 獲取保存失敗的數據
    exportFailData: function() {
      getFailData(this.value)
        .then(res => {
          this.JSONToExcelConvertor(res.data, '未導入成功的數據')
          // this.value = ''
        }).catch()
    },
    // 導出數據到excel
    exportExcel() {
      let titleExcel = ''
      // 獲取表格標題
      for (let i = 0; i < this.options.length; i++) {
        if (this.options[i].template_table_name === this.value) {
          titleExcel = this.options[i].template_description
        }
      }
      // this.tableToExcel(this.template)
      this.JSONToExcelConvertor(this.template, titleExcel)
      // this.exportPathMethod(this.template)
      // this.JSONToExcelConvertor(this.submitLastValue, 'report', this.arr, ['id'])
    },
    exportPathMethod(data) {
      // 要導出的json數據
      var jsonData = []
      // for (var i = 0; i < data.length; i++) {
      //   jsonData.push({
      //     index: i + 1,
      //     title: data[i].title,
      //     url: data[i].url,
      //     createTime: data[i].createTime
      //   })
      // }

      // 列標題,逗號隔開,每個逗號就是隔開一個單元格
      let str = `序號,標題,地址,時間\n`
      // 增長\t爲了避免讓表格顯示科學計數法或者其餘格式
      for (let i = 0; i < jsonData.length; i++) {
        for (const item in jsonData[i]) {
          str += `${jsonData[i][item] + '\t'},`
        }
        str += '\n'
      }

      // encodeURIComponent解決中文亂碼
      const uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(str)
      // 經過建立a標籤實現
      var link = document.createElement('a')
      link.href = uri
      // 對下載的文件命名
      link.download = 'json數據表.xls'
      document.body.appendChild(link)
      link.click()
    },
    // 只轉出excel標題
    JSONToExcelConvertor(JSONData, FileName, title, filter) {
      if (!JSONData) { return }
      var arrData = typeof JSONData !== 'object' ? JSON.parse(JSONData) : JSONData
      var excel = '<table>'
      var row = '<tr>'

      if (title) {
        for (const i in title) {
          row += "<th align='center'>" + title[i] + '</th>'
        }
      } else {
        for (const i in arrData[0]) {
          let num = 0
          for (let j = 0; j < this.templateAllData.length; j++) {
            if (i === this.templateAllData[j].attribute_name && this.templateAllData[j].attribute_not_null === true) {
              num += 1
            }
          }
          if (num === 0) {
            row += "<th align='center'>" + '</span>' + i + '</th>'
          } else {
            // 導出時必填的有*號 row += "<th align='center'><span style='color: red'>" + '*' + '</span>' + i + '</th>'
            row += "<th align='center'> " + i + '</th>'
          }
        }
      }
      excel += row + '</tr>'
      // 若是有須要過濾的項則過濾
      for (var i = 0; i < arrData.length; i++) {
        let row = '<tr>'
        for (var index in arrData[i]) {
          if (filter) {
            if (filter.indexOf(index) === -1) {
              var value = arrData[i][index] == null ? '' : arrData[i][index]
              row += '<td>' + value + '</td>'
            }
          } else {
            const value = arrData[i][index] == null ? '' : arrData[i][index]
            row += "<td align='center'>" + value + '</td>'
          }
        }
        excel += row + '</tr>'
      }
      excel += '</table>'

      var excelFile = "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel' xmlns='http://www.w3.org/TR/REC-html40'>"
      excelFile += '<meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8">'
      excelFile += '<meta http-equiv="content-type" content="application/vnd.ms-excel'
      excelFile += '; charset=UTF-8">'
      excelFile += '<head>'
      excelFile += '<!--[if gte mso 9]>'
      excelFile += '<xml>'
      excelFile += '<x:ExcelWorkbook>'
      excelFile += '<x:ExcelWorksheets>'
      excelFile += '<x:ExcelWorksheet>'
      excelFile += '<x:Name>'
      excelFile += '{worksheet}'
      excelFile += '</x:Name>'
      excelFile += '<x:WorksheetOptions>'
      excelFile += '<x:DisplayGridlines/>'
      excelFile += '</x:WorksheetOptions>'
      excelFile += '</x:ExcelWorksheet>'
      excelFile += '</x:ExcelWorksheets>'
      excelFile += '</x:ExcelWorkbook>'
      excelFile += '</xml>'
      excelFile += '<![endif]-->'
      excelFile += '</head>'
      excelFile += '<body>'
      excelFile += excel
      excelFile += '</body>'
      excelFile += '</html>'
      var uri = 'data:application/vnd.ms-excel;charset=utf-8,' + encodeURIComponent(excelFile)
      var link = document.createElement('a')
      link.href = uri
      link.style = 'visibility:hidden'
      link.download = FileName + '.xls'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
    },
    // 轉出標題和數據
    tableToExcel: function(jsonData) {
      // 列標題
      let str = '<tr>'
      for (let i = 0; i < this.arr.length; i++) {
        str += `<td>${this.arr[i] + '\t'}</td>`
      }
      str += '</tr>'
      // 循環遍歷,每行加入tr標籤,每一個單元格加td標籤
      for (let i = 0; i < jsonData.length; i++) {
        str += '<tr>'
        for (const item in jsonData[i]) {
          // 增長\t爲了避免讓表格顯示科學計數法或者其餘格式
          str += `<td>${jsonData[i][item] + '\t'}</td>`
        }
        str += '</tr>'
      }
      // Worksheet名
      const worksheet = 'Sheet1'

      // 下載的表格模板數據
      const template = `<html xmlns:o="urn:schemas-microsoft-com:office:office"
      xmlns:x="urn:schemas-microsoft-com:office:excel"
      xmlns="http://www.w3.org/TR/REC-html40">
      <head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>
        <x:Name>${worksheet}</x:Name>
        <x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>
        </x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]-->
        </head><body><table>${str}</table></body></html>`
// 下載模板
      window.location.href = 'data:application/vnd.ms-excel;base64,' + this.base64(template)
    },
    base64: function(s) { return window.btoa(unescape(encodeURIComponent(s))) }
  }
}
</script>

<style scoped>
  .excel{
    display: inline-block;
    /*position: relative;*/
    /*right: 90px;*/
  }
  .input-file {
    display: none;
  }
  .selectedList{
    display: block;
    width: 100%;
    height: 34px;
    padding: 0px 0;
    font-size: 14px;
    line-height: 1.42857143;
    color: #555;
    background-color: #fff;
    background-image: none;
    border: 1px solid #ccc;
    border-radius: 4px;
  }
  .diybut{
    display: inline-block;
    width: 135px;
    height: 40px;
  }
  .error-prompt{
    margin: 15px 0;
  }
  .correct-prompt{
    margin: 15px 0;
  }
  .hideTr{
    display: none;
  }
  tr:nth-child(odd) {
    background: #F4F4F4;
  }

</style>
<style>
  .excel .el-dialog__header{
    padding: 20px 20px 10px 40px;
  }
</style>

 

2,引用,註冊,這裏很少說了html

3.調用前端

 <excelData :title-name="titleName" :action-name="actionName" :disabled="!operate_action.import_customer" style="margin-left: -1px" @refleshParent="exportData"/>

備註:vue

titleName: '導入數據',是按鈕的文字,jquery

actionName: 'customer',是向後端傳入的參數,後端會返回對於上圖的表格的顯示的字段,
exportData:是導入成功的時候須要作的處理
相關文章
相關標籤/搜索