<template>
|
<view class="container">
|
<view v-if="loading">加载中...</view>
|
<view v-if="error" class="error">无法加载文件</view>
|
<view v-if="data" class="table-container">
|
<view class="table">
|
<view class="row" v-for="(row, rowIndex) in data" :key="rowIndex">
|
<view
|
class="cell"
|
v-for="(cell, cellIndex) in row"
|
:key="cellIndex"
|
:rowspan="getMergeSpan(rowIndex, cellIndex, 'row')"
|
:colspan="getMergeSpan(rowIndex, cellIndex, 'col')"
|
>
|
{{ cell }}
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<script>
|
import * as XLSX from 'xlsx';
|
|
export default {
|
data() {
|
return {
|
loading: false,
|
error: false,
|
data: null, // 用于存储解析后的 Excel 数据
|
merges: [] // 用于存储合并单元格信息
|
};
|
},
|
onLoad() {
|
this.loadExcelFile();
|
},
|
methods: {
|
async loadExcelFile() {
|
this.loading = true;
|
this.error = false;
|
this.data = null;
|
|
try {
|
// 从本地存储中读取 Base64 数据
|
const base64Data = uni.getStorageSync('excelBase64Data');
|
const arrayBuffer = this.base64ToArrayBuffer(base64Data);
|
|
const workbook = XLSX.read(arrayBuffer, { type: 'buffer' });
|
const firstSheetName = workbook.SheetNames[0];
|
const worksheet = workbook.Sheets[firstSheetName];
|
|
// 初始化合并单元格信息
|
this.initMerge(worksheet);
|
|
// 将工作表转换为 JSON 格式
|
const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
|
|
// 动态计算最大列数
|
const maxColumns = Math.max(...jsonData.map(row => row.length));
|
|
// 为每行填充空单元格
|
const normalizedData = jsonData.map(row => {
|
while (row.length < maxColumns) {
|
row.push(""); // 填充空单元格
|
}
|
return row;
|
});
|
|
this.data = normalizedData;
|
console.log('Normalized Data:', this.data);
|
console.log('Merges:', this.merges);
|
} catch (error) {
|
console.error('Failed to load Excel file:', error);
|
this.error = true;
|
} finally {
|
this.loading = false;
|
}
|
},
|
base64ToArrayBuffer(base64) {
|
const binaryString = atob(base64);
|
const len = binaryString.length;
|
const bytes = new Uint8Array(len);
|
for (let i = 0; i < len; i++) {
|
bytes[i] = binaryString.charCodeAt(i);
|
}
|
return bytes.buffer;
|
},
|
initMerge(worksheet) {
|
const merges = worksheet['!merges'];
|
if (!merges) return;
|
|
this.merges = merges.map(merge => [
|
merge.s.r, merge.s.c, merge.e.r, merge.e.c
|
]);
|
},
|
getMergeSpan(rowIndex, cellIndex, type) {
|
for (const merge of this.merges) {
|
const [startRow, startCol, endRow, endCol] = merge;
|
|
// 检查当前单元格是否在合并范围内
|
if (
|
rowIndex >= startRow &&
|
rowIndex <= endRow &&
|
cellIndex >= startCol &&
|
cellIndex <= endCol
|
) {
|
// 如果是起始单元格,返回合并的行/列跨度
|
if (rowIndex === startRow && cellIndex === startCol) {
|
return type === 'row'
|
? endRow - startRow + 1
|
: endCol - startCol + 1;
|
} else {
|
// 如果不是起始单元格,返回 0,表示该单元格被合并
|
return 0;
|
}
|
}
|
}
|
return 1; // 默认情况下,每个单元格占用一行一列
|
}
|
}
|
};
|
</script>
|
|
<style scoped>
|
.container {
|
padding: 20px;
|
}
|
|
.table-container {
|
overflow-x: auto; /* 添加横向滚动条 */
|
overflow-y: auto; /* 添加纵向滚动条 */
|
max-width: 100%; /* 限制表格宽度 */
|
max-height: 1000px; /* 限制表格高度 */
|
border: 1px solid #ccc;
|
}
|
|
.table {
|
display: table;
|
table-layout: fixed; /* 固定表格布局 */
|
border-collapse: collapse;
|
width: 100%; /* 确保表格宽度占满容器 */
|
}
|
|
.row {
|
display: table-row;
|
}
|
|
.cell {
|
display: table-cell;
|
padding: 8px;
|
border: 1px solid #ccc;
|
text-overflow: ellipsis; /* 超出部分显示省略号 */
|
white-space: nowrap; /* 防止内容换行 */
|
overflow: hidden; /* 隐藏超出内容 */
|
width: 100px; /* 固定单元格宽度 */
|
}
|
|
.error {
|
color: red;
|
}
|
</style>
|