first commit
This commit is contained in:
parent
fbe1f56cca
commit
13fc866e8e
909
package-lock.json
generated
909
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -8,8 +8,11 @@
|
|||||||
"lint": "vue-cli-service lint"
|
"lint": "vue-cli-service lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"axios": "^1.7.9",
|
||||||
"core-js": "^3.8.3",
|
"core-js": "^3.8.3",
|
||||||
"vue": "^2.6.14"
|
"vue": "^2.6.14",
|
||||||
|
"x-data-spreadsheet": "^1.1.9",
|
||||||
|
"xlsx": "^0.16.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.12.16",
|
"@babel/core": "^7.12.16",
|
||||||
@ -19,6 +22,8 @@
|
|||||||
"@vue/cli-service": "~5.0.0",
|
"@vue/cli-service": "~5.0.0",
|
||||||
"eslint": "^7.32.0",
|
"eslint": "^7.32.0",
|
||||||
"eslint-plugin-vue": "^8.0.3",
|
"eslint-plugin-vue": "^8.0.3",
|
||||||
|
"less": "^4.2.1",
|
||||||
|
"less-loader": "^12.2.0",
|
||||||
"vue-template-compiler": "^2.6.14"
|
"vue-template-compiler": "^2.6.14"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<img alt="Vue logo" src="./assets/logo.png">
|
<ExcelComponent msg="Welcome to Your Vue.js App"/>
|
||||||
<HelloWorld msg="Welcome to Your Vue.js App"/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import HelloWorld from './components/HelloWorld.vue'
|
import ExcelComponent from './components/ExcelComponent.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'App',
|
name: 'App',
|
||||||
components: {
|
components: {
|
||||||
HelloWorld
|
ExcelComponent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -23,6 +22,5 @@ export default {
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #2c3e50;
|
color: #2c3e50;
|
||||||
margin-top: 60px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
103
src/components/ExcelComponent.vue
Normal file
103
src/components/ExcelComponent.vue
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<button @click="loadExcel">从MinIO加载Excel文件</button>
|
||||||
|
<button @click="saveExcel">将Excel文件保存至MinIO</button>
|
||||||
|
<div id="x-spreadsheet"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import axios from 'axios';
|
||||||
|
import 'x-data-spreadsheet/dist/xspreadsheet.css';
|
||||||
|
import zhCN from 'x-data-spreadsheet/src/locale/zh-cn';
|
||||||
|
import x_spreadsheet from 'x-data-spreadsheet';
|
||||||
|
import XLSX from 'xlsx';
|
||||||
|
import { stox, xtos } from '@/utils/xlsxspread';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ExcelComponent',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
spreadsheet: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
x_spreadsheet.locale('zh-cn', zhCN);
|
||||||
|
this.spreadsheet = new x_spreadsheet('#x-spreadsheet', {
|
||||||
|
mode: 'edit',
|
||||||
|
showToolbar: true,
|
||||||
|
showGrid: true,
|
||||||
|
showContextmenu: true,
|
||||||
|
showBottomBar: true,
|
||||||
|
view: {
|
||||||
|
height: () => document.documentElement.clientHeight * 0.9,
|
||||||
|
width: () => document.documentElement.clientWidth,
|
||||||
|
},
|
||||||
|
row: {
|
||||||
|
len: 100,
|
||||||
|
height: 25,
|
||||||
|
},
|
||||||
|
col: {
|
||||||
|
len: 26,
|
||||||
|
width: 100,
|
||||||
|
indexWidth: 60,
|
||||||
|
minWidth: 60,
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
bgcolor: '#ffffff',
|
||||||
|
align: 'left',
|
||||||
|
valign: 'middle',
|
||||||
|
textwrap: false,
|
||||||
|
strike: false,
|
||||||
|
underline: false,
|
||||||
|
color: '#0a0a0a',
|
||||||
|
font: {
|
||||||
|
name: 'Helvetica',
|
||||||
|
size: 10,
|
||||||
|
bold: false,
|
||||||
|
italic: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
loadExcel() {
|
||||||
|
const minioUrl = 'http://47.95.198.7:30000/tmp/123.xlsx';
|
||||||
|
|
||||||
|
axios.get(minioUrl, { responseType: 'arraybuffer' })
|
||||||
|
.then(response => {
|
||||||
|
const data = new Uint8Array(response.data);
|
||||||
|
const workbook = XLSX.read(data, { type: 'array' });
|
||||||
|
this.spreadsheet.loadData(stox(workbook));
|
||||||
|
})
|
||||||
|
.catch(error => console.error('加载文件失败:', error));
|
||||||
|
},
|
||||||
|
saveExcel() {
|
||||||
|
const data = this.spreadsheet.getData();
|
||||||
|
const workbook = xtos(data);
|
||||||
|
|
||||||
|
const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
|
||||||
|
const blob = new Blob([excelBuffer], { type: 'application/octet-stream' });
|
||||||
|
|
||||||
|
const minioUploadUrl = 'http://47.95.198.7:30000/tmp/123.xlsx';
|
||||||
|
axios.put(minioUploadUrl, blob, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/octet-stream',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
console.log('文件上传成功', response);
|
||||||
|
})
|
||||||
|
.catch(error => console.error('文件上传失败:', error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#x-spreadsheet {
|
||||||
|
width: 100%;
|
||||||
|
height: 500px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,58 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="hello">
|
|
||||||
<h1>{{ msg }}</h1>
|
|
||||||
<p>
|
|
||||||
For a guide and recipes on how to configure / customize this project,<br>
|
|
||||||
check out the
|
|
||||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
|
||||||
</p>
|
|
||||||
<h3>Installed CLI Plugins</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
|
|
||||||
</ul>
|
|
||||||
<h3>Essential Links</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
|
||||||
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
|
||||||
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
|
||||||
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
|
||||||
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
|
||||||
</ul>
|
|
||||||
<h3>Ecosystem</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
|
||||||
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
|
||||||
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'HelloWorld',
|
|
||||||
props: {
|
|
||||||
msg: String
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
||||||
<style scoped>
|
|
||||||
h3 {
|
|
||||||
margin: 40px 0 0;
|
|
||||||
}
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
li {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: #42b983;
|
|
||||||
}
|
|
||||||
</style>
|
|
121
src/utils/xlsxspread.js
Normal file
121
src/utils/xlsxspread.js
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
import XLSX from "xlsx";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将SheetJS数据转换成x-spreadsheet数据
|
||||||
|
*/
|
||||||
|
export function stox(wb) {
|
||||||
|
var out = [];
|
||||||
|
wb.SheetNames.forEach(function (name) {
|
||||||
|
var o = { name: name, rows: {} };
|
||||||
|
var ws = wb.Sheets[name];
|
||||||
|
if (!ws || !ws["!ref"]) return;
|
||||||
|
var range = XLSX.utils.decode_range(ws['!ref']);
|
||||||
|
// sheet_to_json will lost empty row and col at begin as default
|
||||||
|
range.s = { r: 0, c: 0 };
|
||||||
|
var aoa = XLSX.utils.sheet_to_json(ws, {
|
||||||
|
raw: false,
|
||||||
|
header: 1,
|
||||||
|
range: range
|
||||||
|
});
|
||||||
|
|
||||||
|
aoa.forEach(function (r, i) {
|
||||||
|
var cells = {};
|
||||||
|
r.forEach(function (c, j) {
|
||||||
|
cells[j] = { text: c || String(c) };
|
||||||
|
|
||||||
|
var cellRef = XLSX.utils.encode_cell({ r: i, c: j });
|
||||||
|
|
||||||
|
if (ws[cellRef] != null && ws[cellRef].f != null) {
|
||||||
|
cells[j].text = "=" + ws[cellRef].f;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
o.rows[i] = { cells: cells };
|
||||||
|
});
|
||||||
|
o.rows.len = aoa.length + 1;
|
||||||
|
|
||||||
|
o.merges = [];
|
||||||
|
(ws["!merges"] || []).forEach(function (merge, i) {
|
||||||
|
//Needed to support merged cells with empty content
|
||||||
|
if (o.rows[merge.s.r] == null) {
|
||||||
|
o.rows[merge.s.r] = { cells: {} };
|
||||||
|
}
|
||||||
|
if (o.rows[merge.s.r].cells[merge.s.c] == null) {
|
||||||
|
o.rows[merge.s.r].cells[merge.s.c] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
o.rows[merge.s.r].cells[merge.s.c].merge = [
|
||||||
|
merge.e.r - merge.s.r,
|
||||||
|
merge.e.c - merge.s.c
|
||||||
|
];
|
||||||
|
|
||||||
|
o.merges[i] = XLSX.utils.encode_range(merge);
|
||||||
|
});
|
||||||
|
|
||||||
|
out.push(o);
|
||||||
|
});
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 x-spreadsheet数据转换成SheetJS数据
|
||||||
|
*/
|
||||||
|
export function xtos(sdata) {
|
||||||
|
var out = XLSX.utils.book_new();
|
||||||
|
sdata.forEach(function (xws) {
|
||||||
|
var ws = {};
|
||||||
|
var rowobj = xws.rows;
|
||||||
|
var minCoord = { r: 0, c: 0 }, maxCoord = { r: 0, c: 0 };
|
||||||
|
for (var ri = 0; ri < rowobj.len; ++ri) {
|
||||||
|
var row = rowobj[ri];
|
||||||
|
if (!row) continue;
|
||||||
|
|
||||||
|
Object.keys(row.cells).forEach(function (k) {
|
||||||
|
var idx = +k;
|
||||||
|
if (isNaN(idx)) return;
|
||||||
|
|
||||||
|
var lastRef = XLSX.utils.encode_cell({ r: ri, c: idx });
|
||||||
|
if (ri > maxCoord.r) maxCoord.r = ri;
|
||||||
|
if (idx > maxCoord.c) maxCoord.c = idx;
|
||||||
|
|
||||||
|
var cellText = row.cells[k].text, type = "s";
|
||||||
|
if (!cellText) {
|
||||||
|
cellText = "";
|
||||||
|
type = "z";
|
||||||
|
} else if (!isNaN(Number(cellText))) {
|
||||||
|
cellText = Number(cellText);
|
||||||
|
type = "n";
|
||||||
|
} else if (cellText.toLowerCase() === "true" || cellText.toLowerCase() === "false") {
|
||||||
|
cellText = Boolean(cellText);
|
||||||
|
type = "b";
|
||||||
|
}
|
||||||
|
|
||||||
|
ws[lastRef] = { v: cellText, t: type };
|
||||||
|
|
||||||
|
if (type == "s" && cellText[0] == "=") {
|
||||||
|
ws[lastRef].f = cellText.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row.cells[k].merge != null) {
|
||||||
|
if (ws["!merges"] == null) ws["!merges"] = [];
|
||||||
|
|
||||||
|
ws["!merges"].push({
|
||||||
|
s: { r: ri, c: idx },
|
||||||
|
e: {
|
||||||
|
r: ri + row.cells[k].merge[0],
|
||||||
|
c: idx + row.cells[k].merge[1]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ws["!ref"] = minCoord ? XLSX.utils.encode_range({
|
||||||
|
s: minCoord,
|
||||||
|
e: maxCoord
|
||||||
|
}) : "A1";
|
||||||
|
|
||||||
|
XLSX.utils.book_append_sheet(out, ws, xws.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user