feat: 解析excel为表格
This commit is contained in:
parent
610f138abb
commit
1d4ec35b05
|
|
@ -57,7 +57,8 @@
|
||||||
"screenfull": "^6.0.0",
|
"screenfull": "^6.0.0",
|
||||||
"vue": "^3.3.1",
|
"vue": "^3.3.1",
|
||||||
"vue-i18n": "9.2.2",
|
"vue-i18n": "9.2.2",
|
||||||
"vue-router": "^4.2.0"
|
"vue-router": "^4.2.0",
|
||||||
|
"xlsx": "^0.18.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^17.6.3",
|
"@commitlint/cli": "^17.6.3",
|
||||||
|
|
@ -67,6 +68,7 @@
|
||||||
"@types/lodash": "^4.14.195",
|
"@types/lodash": "^4.14.195",
|
||||||
"@types/nprogress": "^0.2.0",
|
"@types/nprogress": "^0.2.0",
|
||||||
"@types/path-browserify": "^1.0.0",
|
"@types/path-browserify": "^1.0.0",
|
||||||
|
"@types/xlsx": "^0.0.36",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.59.6",
|
"@typescript-eslint/eslint-plugin": "^5.59.6",
|
||||||
"@typescript-eslint/parser": "^5.59.6",
|
"@typescript-eslint/parser": "^5.59.6",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
declare module 'xlsx/xlsx.mjs'
|
||||||
|
|
@ -46,9 +46,46 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
|
<h3>解析excel</h3>
|
||||||
|
<el-upload
|
||||||
|
:disabled="state.fileList.length !== 0"
|
||||||
|
class="upload"
|
||||||
|
drag
|
||||||
|
accept=".xls,.xlsx"
|
||||||
|
:show-file-list="false"
|
||||||
|
action=""
|
||||||
|
:http-request="handleUploadFile"
|
||||||
|
>
|
||||||
|
<i-ep-upload-filled class="icon"></i-ep-upload-filled>
|
||||||
|
<!-- <el-icon class="el-icon--upload"><upload-filled /></el-icon> -->
|
||||||
|
<div class="el-upload__text">拖拽excel到这里</div>
|
||||||
|
</el-upload>
|
||||||
|
<div v-loading="loading" class="excel-table-wrap">
|
||||||
|
<el-table
|
||||||
|
v-if="state.tableExcelHead.length && state.excelTableData.length"
|
||||||
|
:data="state.excelTableData"
|
||||||
|
stripe
|
||||||
|
border
|
||||||
|
style="width: 100%"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
v-for="(item, index) in state.tableExcelHead"
|
||||||
|
:key="index"
|
||||||
|
:prop="item"
|
||||||
|
:label="item"
|
||||||
|
width="150"
|
||||||
|
>
|
||||||
|
<template #default="scope">
|
||||||
|
<span class="overflow-ellipsis">{{ scope.row[item] }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import * as XLSX from "xlsx/xlsx.mjs";
|
||||||
import { cloneDeep } from "lodash-es";
|
import { cloneDeep } from "lodash-es";
|
||||||
|
|
||||||
enum TableCommand {
|
enum TableCommand {
|
||||||
|
|
@ -61,6 +98,7 @@ enum TableCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
let tableData = ref<any[]>([]);
|
let tableData = ref<any[]>([]);
|
||||||
|
const loading = ref(false);
|
||||||
const orginData = [
|
const orginData = [
|
||||||
{
|
{
|
||||||
date: "2016-05-03",
|
date: "2016-05-03",
|
||||||
|
|
@ -103,6 +141,17 @@ const orginData = [
|
||||||
hobby: "游泳",
|
hobby: "游泳",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
const state = reactive({
|
||||||
|
fileList: [],
|
||||||
|
excelData: [],
|
||||||
|
tableHead: [],
|
||||||
|
sheetList: [] as any[],
|
||||||
|
allSheetObj: {} as any,
|
||||||
|
tableExcelHead: [] as string[],
|
||||||
|
activeSheet: "",
|
||||||
|
fileName: "",
|
||||||
|
excelTableData: [],
|
||||||
|
});
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
tableData.value = orginData.map((item) => item);
|
tableData.value = orginData.map((item) => item);
|
||||||
});
|
});
|
||||||
|
|
@ -226,6 +275,100 @@ const sortTableData = (sortCol: ColumnProp) => {
|
||||||
tableData.value = cloneDeep(orginData).map((item: any) => item);
|
tableData.value = cloneDeep(orginData).map((item: any) => item);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const handleUploadFile = (data: any) => {
|
||||||
|
const { file } = data;
|
||||||
|
const { size, name } = file;
|
||||||
|
state.fileName = name;
|
||||||
|
// 获取最后一个.的位置
|
||||||
|
const index = name.lastIndexOf(".");
|
||||||
|
// 获取文件类型
|
||||||
|
const ext = name.substring(index + 1);
|
||||||
|
const accept = ["xlsx", "xls"];
|
||||||
|
if (!accept.includes(ext)) {
|
||||||
|
ElMessage({
|
||||||
|
type: "error",
|
||||||
|
message: "请选择xls或者xlsx文件",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true;
|
||||||
|
readFile(file, "");
|
||||||
|
};
|
||||||
|
const currentSheetName = computed(() => {
|
||||||
|
const find = state.sheetList.find(
|
||||||
|
(item) => item.sheetId === state.activeSheet
|
||||||
|
);
|
||||||
|
return find?.name || "";
|
||||||
|
});
|
||||||
|
|
||||||
|
const getFile = () => {
|
||||||
|
const sheetName = `${currentSheetName.value}`;
|
||||||
|
let workbook = XLSX.utils.book_new();
|
||||||
|
|
||||||
|
workbook = {
|
||||||
|
...workbook,
|
||||||
|
SheetNames: [sheetName],
|
||||||
|
Sheets: {},
|
||||||
|
};
|
||||||
|
workbook.Sheets[sheetName] = state.allSheetObj[sheetName];
|
||||||
|
const wopts = {
|
||||||
|
bookType: "xlsx", // 要生成的文件类型
|
||||||
|
bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
|
||||||
|
type: "binary", // 二进制格式
|
||||||
|
};
|
||||||
|
const wbout = XLSX.write(workbook, wopts);
|
||||||
|
const transform = (s: any) => {
|
||||||
|
const buf = new ArrayBuffer(s.length);
|
||||||
|
const view = new Uint8Array(buf);
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-bitwise
|
||||||
|
for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
|
||||||
|
return buf;
|
||||||
|
};
|
||||||
|
// 字符串转ArrayBuffer
|
||||||
|
const blob = new Blob([transform(wbout)], {
|
||||||
|
type: "application/octet-stream",
|
||||||
|
});
|
||||||
|
const file = new window.File([blob], state.fileName, { type: "xlsx" });
|
||||||
|
};
|
||||||
|
const readFile = (file: any, callback: any) => {
|
||||||
|
const rABS = true; // true: readAsBinaryString ; false: readAsArrayBuffer
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = function (e) {
|
||||||
|
let data = e.target?.result as any;
|
||||||
|
if (!rABS) data = new Uint8Array(data);
|
||||||
|
const readData = XLSX.read(data, {
|
||||||
|
type: rABS ? "binary" : "array",
|
||||||
|
cellText: false,
|
||||||
|
cellDates: true,
|
||||||
|
});
|
||||||
|
const { Sheets, Workbook } = readData;
|
||||||
|
state.sheetList = Workbook.Sheets;
|
||||||
|
state.activeSheet = state.sheetList[0].sheetId;
|
||||||
|
state.allSheetObj = Sheets;
|
||||||
|
const result = XLSX.utils.sheet_to_json(
|
||||||
|
state.allSheetObj[currentSheetName.value],
|
||||||
|
{ raw: false, dateNF: "YYYY-MM-DD HH:mm:ss" }
|
||||||
|
);
|
||||||
|
const allData = XLSX.utils.sheet_to_json(
|
||||||
|
state.allSheetObj[currentSheetName.value],
|
||||||
|
{ header: 1 }
|
||||||
|
);
|
||||||
|
state.tableExcelHead = allData.length > 0 ? allData[0] : Array(10).fill("");
|
||||||
|
state.excelTableData = result;
|
||||||
|
|
||||||
|
// getFile();
|
||||||
|
// 获取表头key
|
||||||
|
if (callback) callback(readData);
|
||||||
|
};
|
||||||
|
if (rABS) {
|
||||||
|
reader.readAsBinaryString(file);
|
||||||
|
} else {
|
||||||
|
reader.readAsArrayBuffer(file);
|
||||||
|
}
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.table-page {
|
.table-page {
|
||||||
|
|
@ -234,7 +377,7 @@ const sortTableData = (sortCol: ColumnProp) => {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
||||||
.table-wrap {
|
.table-wrap {
|
||||||
height: 100%;
|
// height: 100%;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|
||||||
|
|
@ -267,5 +410,27 @@ const sortTableData = (sortCol: ColumnProp) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.upload {
|
||||||
|
margin-top: 16px;
|
||||||
|
border: 2px dashed #90caf9;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: 230px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
background-color: #e3f2fd;
|
||||||
|
:deep(.el-upload-dragger) {
|
||||||
|
background-color: #e3f2fd;
|
||||||
|
border: none;
|
||||||
|
padding: 0px;
|
||||||
|
.icon {
|
||||||
|
font-size: 110px;
|
||||||
|
color: #90caf9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.excel-table-wrap {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 300px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue