<a-upload
:show-upload-list="false"
ref="upload"
:beforeUpload="handleFileUpload"
@change="handleChange"
:customRequest="selectCertFile"
accept=".xlsx, .xls, .csv"
>
<a-button :loading="loading">
<upload-outlined></upload-outlined>
{{ loading ? '上传中...' : '点击上传Excel文件' }}
</a-button>
</a-upload>
<!-- 动态表格 不含表头-->
<a-table
v-if="tableData.length > 0"
:columns="filteredColumns"
:data-source="filteredTableData"
:pagination="false"
bordered size="middle"
:scroll="{ x: 'max-content' }"
:row-class-name="rowTableClassName"
style="margin: 0 10px 10px 10px;" :loading="isloading"
:showHeader="false">
<!-- 自定义单元格以支持合并-->
<template #bodyCell="{ column, record, index }">
<span v-if="record[column.dataIndex]?.value !== 'dropdown'">
{{record[column.dataIndex]?.value}}
</span>
<!-- 解析excel后底部添加下拉选择框-->
<div v-else style="display: flex;flex-wrap: wrap;">
<a-select v-model:value="dropdownValues[column.key][0]"
:autoWidth="false"
style="width: 100%; margin-bottom: 8px;"
placeholder="请选择" :options="provinceOptions"
@change="(value) => handleProvinceChange(column.key, value)" />
<a-select v-model:value="dropdownValues[column.key][1]"
:autoWidth="false"
style="width: 100%; margin-bottom: 8px;" placeholder="请选择"
:options="getCityOptions(column.key)"
@change="(value) => handleCityChange(column.key, value)"
:disabled="!dropdownValues[column.key][0]" />
<a-select v-model:value="dropdownValues[column.key][2]"
:autoWidth="false" style="width: 100%;"
placeholder="请选择" :options="getCountyOptions(column.key)"
show-search :filter-option="filterOption"
:disabled="!dropdownValues[column.key][1]" />
</div>
</template>
</a-table>

<script setup lang="ts">
import { onMounted, reactive, ref, computed, watch } from "vue";
import * as XLSX from "xlsx";
import { UploadOutlined } from "@ant-design/icons-vue";
import { message,notification } from "ant-design-vue";
import { Select } from 'ant-design-vue';
import type { TableProps, FormInstance,SelectProps } from "ant-design-vue";
const loading = ref(false);
const columns = ref([]);
// 表格数据
const tableData = ref([]);
const handleChange = async (info: any) => {
}
const selectCertFile = (info: any) => {
};
const handleFileUpload = (file:any) => {
loading.value = true;
const reader = new FileReader();
reader.onload = (e: any) => {
try {
const data = new Uint8Array(e.target.result);
const workbook = XLSX.read(data, { type: "array" });
if (workbook.SheetNames.length > 1) {
message.error('文件包含多个Sheet页');
return false; // 阻止上传
}
const sheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[sheetName];
// 获取合并单元格的信息
const merges = worksheet["!merges"] || [];
// 解析数据范围
const range = XLSX.utils.decode_range(worksheet["!ref"]);
const jsonData = [];
const jsonAllData = [];
const maxRows = Math.min(range.e.r + 1, 10);
for (let row = range.s.r; row <= range.e.r; row++) {
const rowData = {};
for (let col = range.s.c; col <= range.e.c; col++) {
const cellAddress = XLSX.utils.encode_cell({ r: row, c: col });
const cellValue = worksheet[cellAddress]?.v || "";
rowData[`col${col}`] = { value: cellValue, rowSpan: 1, colSpan: 1 };
// 初始化 rowSpan 和 colSpan
}
if (row - range.s.r < maxRows) {
jsonData.push({ ...rowData, key: row }); //只展示前10行数据
}
jsonAllData.push({ ...rowData, key: row }); // 每一行添加唯一 key
}
// 动态生成列配置,并移除所有单元格为空的列
const columnsConfig = Array.from({ length: range.e.c - range.s.c + 1 }, (_, i) => `col${range.s.c + i}`);
const filteredColumns = columnsConfig.filter(colKey => {
return jsonData.some(row => row[colKey].value.trim() !== "");
});
columns.value = filteredColumns.map((colKey, index) => ({
title: "",
dataIndex: colKey,
key: colKey,
width: "180px",
ellipsis: true,
customCell: (record, rowIndex) => {
const cell = record[colKey];
return {
rowSpan: cell.rowSpan ?? 1,
colSpan: cell.colSpan ?? 1,
};
},
}));
// 处理合并单元格
merges.forEach((merge) => {
const { s, e } = merge; // s 是开始单元格,e 是结束单元格
// 遍历需要合并的区域
// 检查合并单元格是否在有效范围内
if (s.r >= range.s.r && s.c >= range.s.c && e.r <= range.e.r && e.c <= range.e.c) {
for (let row = s.r; row <= e.r; row++) {
for (let col = s.c; col <= e.c; col++) {
const colKey = `col${col}`;
if (filteredColumns.includes(colKey)) {
if (row === s.r && col === s.c) {
jsonData[row][colKey].rowSpan = e.r - s.r + 1;
jsonData[row][colKey].colSpan = e.c - s.c + 1;
} else {
jsonData[row][colKey].rowSpan = 0;
jsonData[row][colKey].colSpan = 0;
}
}
}
}
}
});
const dropdownRow = {};
//底部添加行
columns.value.forEach((col, index) => {
dropdownRow[col.dataIndex] = { value: 'dropdown', rowSpan: 1, colSpan: 1 }; // 标记为dropdown类型
dropdownValues[col.key] = ['', '', '']; // 初始化dropdownValues
});
jsonData.push({ ...dropdownRow, key: jsonData.length });
tableData.value = jsonData;
//-------------------------- 上传接口--------------------------------
//let formDatas = new FormData();
//formDatas.append("file", file);
//formDatas.append("pid", listForm.value.pid);
//formDatas.append("type", '1');
//isloading.value = true;
//selectedRows.value = []
//uploadSalary(formDatas).then((res: any) => {
//if(res.status == 200){
// isloading.value = false;
//message.success('文件解析成功');
//fileListId.value = res.file_id;
//headerIndex.value = res.headernum;
//openTable.value = true;
// for(var i = 0; i < res.headernum+1; i++){
// selectedRows.value.push(i)
//}
//}else{
// message.error(res.error);
// isloading.value = false;
// openTable.value = false;
// }
// })
//.catch((error: any) => {
// isloading.value = false;
// if (error.response) {
// const status = error.response.status;
// if (status === 422) {
// message.error(error.response.data.error);
// } else {
// message.error(error.message);
// }
// } else {
// message.error(error.message);
//}
// });
} catch (error) {
message.error("文件解析失败,请检查文件内容!");
} finally {
loading.value = false;
}
};
reader.readAsArrayBuffer(file);
return false;
};
// 过滤掉空白列和对应的列配置
const filteredColumns = computed(() => {
const nonEmptyColumns = columns.value.filter((column, index) => {
return tableData.value.some(row => row[`col${index}`]?.value !== "");
});
return nonEmptyColumns;
});
//处理表格数据
const filteredTableData = computed(() => {
return tableData.value.map(row => {
const newRow: any = {};
filteredColumns.value.forEach((column, index) => {
newRow[column.dataIndex] = row[column.dataIndex];
});
newRow.key = row.key; // 确保每一行都有唯一的 key
return newRow;
});
});
</script>