Vue carga y lee Excel, lo formatea en una matriz y lo envía al backend, y devuelve el flujo de archivos para exportar Excel al local.

Requisitos:
La lista tiene una columna para el estado de listo para usar, que debe modificarse uniformemente cuando hay demasiados datos.
1. Haga clic en el botón para carga y descarga masiva
2. Un cuadro emergente para la importación por lotes, como se muestra en la Figura 1. 3. Haga clic para descargar la
plantilla, como se muestra en la Figura 2. La plantilla está definida por los dos campos definido por el front-end.Archivo
, como se muestra en la Figura 3
5. Haga clic en Importar, leerá el Excel cargado para verificar si cada línea de datos está calificada y luego la convertirá en una matriz como un parámetro para el fondo, como se muestra en la Figura 4
6. El back-end devolverá un flujo de archivos, y el front-end descargará directamente a Excel local

Conocimiento involucrado:
1. Usando la biblioteca js-xlsx, el front-end lee archivos de informe de Excel
2. Lee archivos locales para comprender los métodos y eventos del objeto FileReader y el embellecimiento del botón de carga.
3. El front-end recibe el flujo de archivos y lo descarga localmente

Después de la imagen, implemente
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
el código para el código:

lista.vue

<template>
	<div>
      <el-button type="primary" @click="add" size="mini">批量上下架</el-button>
      <up-loader ref="addUploader" @downLoad="addExcelExport" @upLoad="addExcelImport"></up-loader>
    </div>
</template>

<script>
import UpLoader from "@/module/components/uploader/uploader.vue"
import eportsheet from '@/module/components/exportsheet/exportsheet'
export default {
      
      
	components: {
      
       UpLoader },
	data() {
      
      
    	return {
      
      
			importAddConfig: {
      
      
		        skuCode: '商品编码(SGU)',
		        priceStatusStr: '上下架状态',
		    },
		}
	},
	methods: {
      
      
		// 打开弹框
		add() {
      
      
	      this.$refs.addUploader.open()
	    },
	    // 下载模版
	    addExcelExport() {
      
      
	      eportsheet.exportFileByConfig([{
      
      }], `批量上下架模板.xlsx`, this.importAddConfig)
	    },
	    async addExcelImport(file) {
      
      
	      let parseConfig = {
      
      }
	      for (let key in this.importAddConfig) {
      
      
	        parseConfig[this.importAddConfig[key]] = key
	      }
	      await eportsheet.parseToJSON(file, parseConfig).then(result => {
      
      
	
	        if(!result){
      
      
	          this.$notify.error({
      
       title: '提示', message:"上传文件数据解析为空" })
	          return false
	        }
	        for(let i=0; i<result.length; i++){
      
      
	          let row = result[i]
	          if(!row.skuCode){
      
      
	            this.$notify.error({
      
       title: '提示', message:"商品编码(SGU)不能为空" })
	            return false
	          }
	          if(!row.priceStatusStr){
      
      
	            this.$notify.error({
      
       title: '提示', message:"上下架状态不能为空" })
	            return false
	          }
	        }
	        // responseType:'blob' 下载文件流设置返回类型blob
	        this.$http.post(`${ 
        api.updateStatusByList}ForExcel`, result, {
      
      }, 'blob').then(res => {
      
      
	          if (res) {
      
      
	              // 关闭弹框
	              this.$refs.addUploader.close()
	              this.$notify.success({
      
      title: '操作提示',message: "上传成功"})
	              // 刷新list表格
	              this.search()
	              // 后端返回的文件流下载到本地
	              this.exportLoading = false
	              var blob = new Blob([res], {
      
      type: 'application/ms-excel'});
	              var elink = document.createElement('a');
	              elink.download = '批量上下架结果' + '.xlsx';
	              elink.href = URL.createObjectURL(blob);
	              document.body.appendChild(elink);
	              elink.click(); //点击下载
	              document.body.removeChild(elink); //下载完成移除元素
	              window.URL.revokeObjectURL(elink); //释放掉blob对象
	              this.loading = false
	              return
	          } else {
      
      
	            this.$notify.error({
      
      
	              title: '提示',
	              message: res.msg
	            })
	          }
	        })
	      })
	    },
	}
}
</script>

UpLoader.vue

<template>
  <!--批量导入弹窗-->
  <el-dialog :visible.sync="visible" size="large" title="批量导入" :loading="loadingInfo">
    <el-row class="mv10">
      <el-col :span="24">
        <label :for="`excelFile${tmp}`" class="excelFileLabel">
          <span class="file-label-text">请选择文件</span>
          <input accept=".xlm,.xls,.xlt,.xlw,.xlsx" type="file" :id="`excelFile${tmp}`" hidden @change="handleFileSelect" :value="fileValue" />
          <el-input class="search-input" v-model="file.name" disabled></el-input>
        </label>
        <el-button style="margin-left: 10px" size="small" type="text" @click="exportTemp">下载模版</el-button>
      </el-col>
    </el-row>
    <el-row>
      <el-col :span="24">
        <el-button style="margin-top: 20px" :loading="loadingInfo" size="small" type="primary" @click="submitUpload">导入
        </el-button>
        <el-button @click="exportErrorFile" v-if="upStatus.code">下载错误列表</el-button>
      </el-col>
    </el-row>
    <el-row class="mt20" v-if="upStatus.code">
      <el-col :span="24" style="color:red">
        <p>{
   
   {file.name}} 导入失败,请修改后重新上传</p>
        <p>失败原因:{
   
   {upStatus.msg}}</p>
      </el-col>
    </el-row>
  </el-dialog>
</template>
<script>

export default {
      
      
  name: 'upLoader',
  props: {
      
      
    loadingInfo: {
      
       type: Boolean, default: false }
  },
  data () {
      
      
    return {
      
      
      tmp: Date.now(),
      visible: false,
      fileValue: '',
      loading: false,
      file: {
      
       name: '' },
      upStatus: {
      
      
        code: '',
        msg: '',
        data: []
      },
      tempConfig: {
      
      }
    }
  },
  methods: {
      
      
    handleFileSelect (e) {
      
      
      this.file = e.target.files[0] || {
      
       name: '' }
      // 如果文件改变需要初始化上传状态
      this.upStatus = {
      
       code: '', msg: '', data: [] }
    },
    exportTemp () {
      
      
      try {
      
      
        this.$emit('downLoad')
      } catch (e) {
      
      
        this.$notify.error({
      
      
          title: '提示',
          message: '模板下载遇到错误'
        })
      }
    },
    submitUpload () {
      
      
      if (!this.file.name || this.file.name.indexOf(".xl") === -1) {
      
      
        this.$notify.warning({
      
      
          title: '提示',
          message: '请选择excel文件'
        })
        return
      }
      this.$emit('upLoad', this.file)
    open () {
      
      
      this.visible = true
      this.fileValue = ''
      this.file = {
      
       name: '' }
    },
    close () {
      
      
      this.visible = false
    }
  }
}
</script>
<style scoped>
.file-label-text {
      
      
  cursor: pointer;
  color: #409eff;
}
</style>

eportsheet.js

import XLSX from 'xlsx'
import * as util from '@/utils/utils'

// 下载模版
function exportFileByConfig (json, fileName, exportConfig, extraData = []) {
    
    
  if (exportConfig) {
    
    
    json = json.map((item, index) => {
    
    
      let newItem = {
    
    }
      for (let k of Object.keys(exportConfig)) {
    
    
        let value = item[k]
        if (value === true) {
    
    
          value = '是'
        }
        if (value === false) {
    
    
          value = '否'
        }
        if (value === null || value === undefined) {
    
    
          value = ''
        }
        newItem[exportConfig[k]] = value
      }
      return newItem
    })
  }
  createFile(json, fileName, extraData)
}
// 创建文件并下载
function createFile (json, fileName, extraList) {
    
    
  let _tmpdata = json[0]
  json.unshift({
    
    })
  var keyMap = [] // 获取keys
  for (var k in _tmpdata) {
    
    
    keyMap.push(k)
    json[0][k] = k
  }
  let tmpdata = [] // 用来保存转换好的json
  let blankNum = extraList.length ? 2 : 1
  console.log('extraList', extraList)
  json.map((v, i) => keyMap.map((k, j) => Object.assign({
    
    }, {
    
    
    v: v[k],
    // position: (j > 25 ? getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1 + extraList.length) // 开头加个空行
    position: (j > 25 ? getCharCol(j) : String.fromCharCode(65 + j)) + (i + blankNum)
  }))).reduce((prev, next) => prev.concat(next)).forEach((v, i) => {
    
    
    tmpdata[v.position] = {
    
    
      v: v.v
    }
  })
  let temObj = {
    
    }
  for (let i = 0; i < extraList.length; i++) {
    
    
    let item = extraList[i]
    for (let j = 0; j < item.length; j++) {
    
    
      let key = String.fromCharCode(65 + i) + (j + 1)
      temObj[key] = {
    
    v: item[j].label + item[j].value}
    }
  }
  tmpdata = Object.assign(temObj, tmpdata)
  var outputPos = Object.keys(tmpdata) // 设置区域,比如表格从A1到D10
  var tmpWB = {
    
    
    SheetNames: ['mySheet'], // 保存的表标题
    Sheets: {
    
    
      'mySheet': Object.assign({
    
    },
        tmpdata, // 内容
        {
    
    
          '!ref': 'A1' + ':' + outputPos[outputPos.length - 1] // 设置填充区域
        })
    }
  }
  let wbout = XLSX.write(tmpWB, {
    
    bookType: 'xlsx', type: 'binary'})
  /* force a download */
  let tmpDown = new Blob([s2ab(wbout)], {
    
    type: 'application/octet-stream'})
  var href = URL.createObjectURL(tmpDown) // 创建对象超链接
  var a = document.createElement('a')
  a.href = href // 绑定a标签
  a.download = fileName || `导出数据${
      
      util.formatDate(new Date())}.xlsx`
  document.body.appendChild(a)
  a.click() // 模拟点击实现下载
  document.body.removeChild(a)
  setTimeout(function () {
    
     // 延时释放
    URL.revokeObjectURL(tmpDown) // 用URL.revokeObjectURL()来释放这个object URL
  }, 100)
}

/*  读取导入的Excel
 *  @excelFile File
 *  @config Object 解析字段
 *  @setter Object XLSX.utils.sheet_to_json的配置
*/
function parseToJSON (excelFile, config, setter = {
     
     }) {
    
    
  return new Promise((resolve, reject) => {
    
    
    if (window.FileReader) {
    
     // 判断浏览器是否支持FileReader对象
      let result = []
      let fr = new FileReader() // 新建文件读取
      fr.readAsBinaryString(excelFile) // 将文件读取二进制码
      fr.onload = ev => {
    
     // 数据读取成功完成时触发
        try {
    
    
          let data = ev.target.result
          // 以二进制流方式读取得到整份excel表格对象
          let workbook = XLSX.read(data, {
    
    
            type: 'binary'
          })
          // 只遍历第一个表
          let name = workbook.SheetNames[0]
          let sheet = workbook.Sheets[name]
          if (sheet) {
    
    
            result = XLSX.utils.sheet_to_json(sheet, {
    
    })
            if (config) {
    
    
              for (let item of result) {
    
    
                for (let excelTitleKey in config) {
    
    
                  item[config[excelTitleKey]] = ''
                }
              }
              result.forEach(item => {
    
    
                for (let key in item) {
    
    
                  if (config[key]) {
    
    
                    item[config[key]] = item[key].toString().trim()
                    delete item[key]
                  }
                }
              })
              // 去空行
              if (result && result.length) {
    
    
                let keyList = Object.keys(result[0])
                for (let i = result.length - 1; i > 0; i--) {
    
    
                  let value = ''
                  for (let key of keyList) {
    
    
                    value += result[i][key]
                  }
                  if (value.trim() === '') {
    
    
                    result.splice(i, 1)
                  }
                }
              }
            }
          }
          resolve(result)
        } catch (e) {
    
    
          reject(new Error('文件类型不正确'))
        }
      }
      return
    }
    reject(new Error('该浏览器不支持该功能,请更换或升级浏览器'))
  })
}


export default {
    
    
  exportFile,
  exportFileByConfig,
}

solicitud.js

/**
 * @description: RequestBody请求
 * @param {_url} 请求地址
 * @param {_params} 请求参数
 * @param {_oParam} 其他参数,用于控制一些非正常现象  urlType: 1:登录接口   其它:正常接口
 * @return:
 */
const post = (_url, _params = {
     
     }, _oParam, resType, boomdebug) => {
    
    
  return axios({
    
    
    method: "post",
    url: formatUrl(_url, boomdebug),
    data: formatParams(_params),
    responseType: resType ? resType : 'json',
    headers: setHeaders('body', _oParam)
  });
};

export default {
    
    
  post,
}

Supongo que te gusta

Origin blog.csdn.net/guairena/article/details/123820481
Recomendado
Clasificación