美文网首页
vue中上传excel并在线(json)编辑

vue中上传excel并在线(json)编辑

作者: 时间煮鱼 | 来源:发表于2023-03-13 16:47 被阅读0次

    上传excel文件,通过xlsx将文件转为json,json文件通过codemirror(vue2版本)在线编辑,编辑后的文件替换第一次上传的文件

    20230314_160827.gif

    安装组件

    1.安装xlsx
    "xlsx": "^0.18.5"
    2.安装vue-codemirror
    "codemirror": "^5.46.0"
    "vue-codemirror": "^4.0.6"

    步骤流程

    1.上传excel文件
    2.excel文件通过xlxs组件转为json
    3.json文件在线展示并编辑
    4.将编辑后的json文件在生成file上传替换

    部分代码

    1、文件上传,使用element-ui上传组件
    <el-upload
            class="upload-demo"
              drag
              :action="actionUrl"
              :on-success="handleSuccess"
              :before-upload="beforeUpload"
              :on-remove="handleRemove"
              :limit="1"
              :file-list="fileList"
              :on-preview="handlePreview"
              accept=".xls, .xlsx"
            >
              <i class="el-icon-upload"></i>
              <div class="el-upload__text">
                <em>点击</em> 或将文件拖拽到这里上传
              </div>
            </el-upload>
    
    2、点击预览
    handlePreview(row) {
          this.codeMirrorVisible = true;
          this.$nextTick(() => {
            this.$refs.codeMirror.url = row.url;  // 文件url
            this.$refs.codeMirror.fileName = row.name; // 文件name
            this.$refs.codeMirror.init(); 
          })
        },
    
    3、弹框显示(在线编辑json组件)
    // appendToBody属性可不写,解决两个dialog弹框叠加,详情查看element-ui文档
    // 引用方式不写了,就import xxx 的,懂得都懂,code-mirror组件代码在下面
    <code-mirror v-if="codeMirrorVisible" ref="codeMirror" :appendToBody="true" @changeFile="changeFile" />
    // @changeFile回调修改fileList,就是将上传文件替换下
    changeFile(data) {
          this.fileList = [{
            name: data.name, // 文件name,自行修改
            url: `${window.SITE_CONFIG["downloadURL"]}/${data.id}` // 文件url,自行修改
          }]
        },
    
    4、在线编辑弹框(组件code-mirror代码)
    <template>
      <el-dialog
        :visible.sync="visible"
        title="在线编辑"
        :close-on-click-modal="false"
        :close-on-press-escape="false"
        :append-to-body="appendToBody"
        width="800px"
      >
        <commonEditor :value="value" language="javescript" @input="change"></commonEditor>
        <template slot="footer">
          <el-button size="small" @click="visible = false">取消</el-button>
          <el-button type="primary" size="small" @click="dataFormSubmitHandle()">确认</el-button>
        </template>
      </el-dialog>
    </template>
    
    <script>
    import Cookies from "js-cookie";  // 可以删除
    import commonEditor from "@/components/common-editor.vue";
    import * as XLSX from "xlsx/xlsx.mjs";
    export default {
      props: ["appendToBody"],
      components: { commonEditor },
      data() {
        return {
          actionUrl: `${window.SITE_CONFIG["uploadURL"]}?token=${Cookies.get(
            "token"
          )}`, // 修改成个人接收file文件地址
          visible: false,
          url: "",
          fileName: "",
          value: "",
          changeInput: ""
        };
      },
      methods: {
        init() {
          this.visible = true;
          // 将在线文件转为json
          // this.url 就是上面2中的this.$refs.codeMirror.url = row.url;  // 文件url
          this.$http.get(this.url, { responseType: "arraybuffer" }).then(res => {
            const data = new Uint8Array(res.data);
            let workbook = XLSX.read(data, { type: "array" });
            let firstSheetName = workbook.SheetNames[0];
            let worksheet = workbook.Sheets[firstSheetName];
            this.value = XLSX.utils.sheet_to_json(worksheet);
          });
        },
        change(value) {
          this.changeInput = value;
        },
        // 点击确认,将修改后的json,转为blob,再转为file,(也可以直接导出file)
        dataFormSubmitHandle() {
          const ws = XLSX.utils.json_to_sheet(JSON.parse(this.changeInput));
          const wb = XLSX.utils.book_new();
          XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
          // const file = XLSX.writeFile(wb, this.fileName); // 直接浏览器导出excel文件
          // 将文件转为file重新上传
          const wbout = XLSX.write(wb, {
            bookType: "xlsx",
            bookSST: true,
            type: "array"
          });
          const blob = new Blob([wbout], {
            type: "application/octet-stream;charset=utf-8"
          });
          const file = new File([blob], this.fileName, { type: "xls/xlsx" });
          const fileParams = new FormData();
          fileParams.append("file", file);
          this.$http
            .post(this.actionUrl, fileParams, {
              headers: {
                "Content-Type": "multipart/form-data"
              }
            })
            .then(({ data: res }) => {
              if (res.code != 0) {
                return this.$message.er;
              }
              this.$emit("changeFile", res.data); // 替换文件
              this.visible = false;
            });
        }
      }
    };
    </script>
    
    <style>
    </style>
    
    5、vue-codemirror(组件commonEditor代码)
    <template>
      <div class="json-editor">
        <textarea ref="textarea" />
      </div>
    </template>
    
    <script>
    import CodeMirror from "codemirror";
    import "codemirror/addon/lint/lint.css";
    import "codemirror/lib/codemirror.css";
    import "codemirror/theme/panda-syntax.css";
    import "codemirror/mode/javascript/javascript";
    import "codemirror/addon/lint/json-lint";
    // 折叠代码
    import "codemirror/addon/fold/foldgutter.css";
    import "codemirror/addon/fold/foldcode.js";
    import "codemirror/addon/fold/foldgutter.js";
    import "codemirror/addon/fold/brace-fold.js";
    import "codemirror/addon/fold/xml-fold.js";
    import "codemirror/addon/fold/indent-fold.js";
    import "codemirror/addon/fold/markdown-fold.js";
    import "codemirror/addon/fold/comment-fold.js";
    
    export default {
      props: ["value"],
      data() {
        return {
          jsonEditor: null
        };
      },
      watch: {
        value(value) {
          const editor_value = this.jsonEditor.getValue();
          if (value !== editor_value) {
            this.jsonEditor.setValue(JSON.stringify(this.value, null, 2));
          }
        }
      },
      mounted() {
        this.jsonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
          lineNumbers: true,
          mode: "application/json",
          gutters: [
            "CodeMirror-lint-markers",
            "CodeMirror-linenumbers",
            "CodeMirror-foldgutter"
          ],
          theme: "panda-syntax",
          lint: true,
          foldGutter: {
            rangeFinder: new CodeMirror.fold.combine(
              CodeMirror.fold.indent,
              CodeMirror.fold.comment
            )
          }
        });
    
        this.jsonEditor.setValue(JSON.stringify(this.value, null, 2));
        this.jsonEditor.on("change", cm => {
          this.$emit("changed", cm.getValue());
          this.$emit('input', cm.getValue())
        });
      }
    };
    </script>
    
    <style lang="scss" scoped>
    .json-editor {
      max-height: 500px;
      overflow: auto;
      position: relative;
      ::v-deep.CodeMirror {
        height: auto;
        min-height: 180px;
      }
      ::v-deep.CodeMirror-scroll {
        min-height: 180px;
      }
      ::v-deep.cm-s-rubyblue span.cm-string {
        color: #f08047;
      }
    }
    </style>
    

    相关文章

      网友评论

          本文标题:vue中上传excel并在线(json)编辑

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