美文网首页
vue中导入功能可视化的方法

vue中导入功能可视化的方法

作者: 带熊二来看简书 | 来源:发表于2020-02-23 12:02 被阅读0次

    前言

    关于Excel 数据导入和导出,比起纯后端解析,前端更有优势,一来是现在的个人电脑的性能已经有了长足的进步,二来,服务端的资源本就金贵,后端服务的瓶颈就是业务系统平台的瓶颈。

    核心技术栈

    xlsx
    npm中搜索xlsx,就可以发现xlsx的所有功能。xlsx应该是bug最少也最稳定的,此外,还有xlsx-style和js-xlsx,它们在原有的功能基础上,添加了对导出样式的控制,让导出的Excel更加满足业务需要。这些都是或多或少的引用了xlsx的官方代码,在此基础上,进行了扩展开发。具体此处不再详细介绍,如需了解,请前往查看

    思路

    • 前端读取excel文件,转为数组;
    • 将数组进行截取,通过for循环分批传给后端,后端进行数据的检测;
    • 后端检测无误后,前端再次for循环将数据传给后端,后端进行导入;
    • 导入完成,前端调用列表接口,刷新数据;

    用到的依赖库

    npm install xlsx --save
    

    部分源码

    <template>
      <div>
        <el-button @click="importDialogFlag=true">导入</el-button>
        <el-dialog :visible.sync="importDialogFlag" title="导入" center>
          <div style="margin-bottom:20px;display:flex">
            <el-upload class="upload" ref="upload" action="/" :multiple="true" :show-file-list="false" :on-change="selectExcel" :limit=1 :auto-upload="false">
              <el-button icon="el-icon-upload" size="small" type="primary">选择文件</el-button>
            </el-upload>
            <el-tag style="margin-left:10px;" v-show="fileName">{{fileName}}</el-tag>
          </div>
          <div style="margin-bottom:20px">
            <el-button type="success" size="small" @click="imports()" >开始导入</el-button>
            <div style="margin-top:20px">
              <el-progress :text-inside="true" :stroke-width="18" :percentage="percentNum" ></el-progress>
            </div>
          </div>
        </el-dialog>
      </div>
    </template>
    
    <script>
      import XLSX from 'xlsx';
      export default{
        data(){
          return{
            importDialogFlag:false,//导入弹窗开关
            fileName:'',//导入的文件名
            importData:[],//表格数据
            percentNum:0,//进度条百分比
            importMsg:'',//错误信息
          }
        },
        methods: {
          //选择文件后的操作
          async selectExcel(file){
            const types = file.name.split(".")[1];//types为选中文件的类型
            const fileType = ["xlsx", "xlc", "xlm", "xls", "xlt", "xlw", "csv"].some(item => item === types);//判断选择的文件是否为支持的格式,返回Boolean
            if (!fileType) {
              this.$message('文件格式错误');
              this.$refs["upload"].clearFiles();
              return;
            }
            this.fileName = file.name;//文件名赋值
            let res=await this.file2Xce(file);//res为读取到的表格数据
            if (res && res.length > 0) {
              res[0].sheet.map(item => {
                this.importData.push(item);
              });
            }
          },
          //读取表格文件的方法,这是一个promise,返回表格数据
          file2Xce(file) {
            return new Promise(function(resolve, reject) {
              // 创建FileReader对象,将文件内容读入内存
              const reader = new FileReader();
              reader.onload = function(e) {
                const data = e.target.result;
                this.wb = XLSX.read(data, {
                  type: "binary"
                });
                const result = [];
                this.wb.SheetNames.forEach(sheetName => {
                  result.push({
                    sheetName: sheetName,
                    sheet: XLSX.utils.sheet_to_json(this.wb.Sheets[sheetName])
                  });
                });
                resolve(result);
              };
              reader.readAsBinaryString(file.raw);
            });
          },
          imports(){
            let cyclic; //循环次数
            let cyclicNum = 1; // 每次导入的条数
            let importDatas=[]; //每次传入的数据
            if (this.importData.length == 0) {
              this.$message('请选择文件');
              return;
            }
            cyclic = Math.ceil(this.importData.length / cyclicNum);
            for (let i = 0; i < cyclic; i++) { //第一次for循环进行数据检测
              let x = i * cyclicNum;
              let y = (i + 1) * cyclicNum;
              if (y > this.importData.length) {
                //判断截取的Y值
                y = this.importData.length;
              }
              importDatas = this.importData.slice(x, y); //用slice方法分批传数据
              this.percentNum = Number((((i + 1) / cyclic) * 100).toFixed(2)); //进度条的百分比
              if (this.percentNum >= 100) {//判断百分比
                this.percentNum = 100;
              }
              /* 开始调用接口 */
              // let res = await equipmentImportTest_api({
              //   deviceImportList: importsData
              // });
              /* 对错误信息进行赋值 */
              // if (res.data.code == 512) {
              //   this.errMsg = true;
              //   this.importMsg = this.importMsg.concat(res.data.msg[0].errorMessage);
              //   this.importMsgs = this.importMsgs.concat(
              //     res.data.msg[1].errorMessage
              //   );
              //   this.importMsgss = this.importMsgss.concat(
              //     res.data.msg[2].errorMessage
              //   );
              // }
            }
            if (!this.importMsg) {//判断没有错误信息
              this.percentNum = 1;//清空进度条
              for (let i = 0; i < cyclic; i++) {//第二次for循环正式导入
                let x = i * cyclicNum;
                let y = (i + 1) * cyclicNum;
                if (y > this.importData.length) {
                  y = this.importData.length;
                }
                importDatas = this.importData.slice(x, y); //分批传数据
                // let res = await equipmentImport_api({//调用导入接口
                //   deviceImportList: importDatas
                // });
                this.percentNum = Number((((i + 1) / cyclic) * 100).toFixed(2)); //进度条的百分比
                if (this.percentNum >= 100) {
                  this.percentNum = 100;
                }
              }
          }
          }
        },
      }
    </script>
    

    相关文章

      网友评论

          本文标题:vue中导入功能可视化的方法

          本文链接:https://www.haomeiwen.com/subject/djhhqhtx.html