上傳excel文件鲸伴,通過xlsx將文件轉(zhuǎn)為json,json文件通過codemirror(vue2版本)在線編輯航邢,編輯后的文件替換第一次上傳的文件
安裝組件
1.安裝xlsx
"xlsx": "^0.18.5"
2.安裝vue-codemirror
"codemirror": "^5.46.0"
"vue-codemirror": "^4.0.6"
步驟流程
1.上傳excel文件
2.excel文件通過xlxs組件轉(zhuǎn)為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> 或?qū)⑽募献У竭@里上傳
</div>
</el-upload>
2嫉鲸、點擊預(yù)覽
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回調(diào)修改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;
// 將在線文件轉(zhuǎn)為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,轉(zhuǎn)為blob冰抢,再轉(zhuǎn)為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文件
// 將文件轉(zhuǎn)為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>