|
@@ -67,7 +67,7 @@
|
|
|
<div class="print-meta">打印时间: {{ new Date().toLocaleString() }}</div>
|
|
<div class="print-meta">打印时间: {{ new Date().toLocaleString() }}</div>
|
|
|
</div>
|
|
</div>
|
|
|
<table class="wide-table">
|
|
<table class="wide-table">
|
|
|
- <thead>
|
|
|
|
|
|
|
+ <!-- <thead>
|
|
|
<tr>
|
|
<tr>
|
|
|
<th v-for="(col, index) in columns" :key="index"
|
|
<th v-for="(col, index) in columns" :key="index"
|
|
|
:style="getColumnStyle(col)"
|
|
:style="getColumnStyle(col)"
|
|
@@ -75,10 +75,23 @@
|
|
|
{{ col.label }}
|
|
{{ col.label }}
|
|
|
</th>
|
|
</th>
|
|
|
</tr>
|
|
</tr>
|
|
|
|
|
+ </thead> -->
|
|
|
|
|
+ <thead>
|
|
|
|
|
+ <tr v-for="(row, rowIndex) in headerRows" :key="'row-' + rowIndex">
|
|
|
|
|
+ <th
|
|
|
|
|
+ v-for="(col, colIndex) in row"
|
|
|
|
|
+ :key="'col-' + colIndex"
|
|
|
|
|
+ :rowspan="col.rowspan"
|
|
|
|
|
+ :colspan="col.colspan"
|
|
|
|
|
+ :style="{ width: col.width + 'px' }"
|
|
|
|
|
+ >
|
|
|
|
|
+ {{ col.label }}
|
|
|
|
|
+ </th>
|
|
|
|
|
+ </tr>
|
|
|
</thead>
|
|
</thead>
|
|
|
<tbody>
|
|
<tbody>
|
|
|
<tr v-for="(row, rowIndex) in getPageData(page)" :key="rowIndex">
|
|
<tr v-for="(row, rowIndex) in getPageData(page)" :key="rowIndex">
|
|
|
- <td v-for="(col, colIndex) in columns" :key="colIndex"
|
|
|
|
|
|
|
+ <td v-for="(col, colIndex) in tableFields" :key="colIndex"
|
|
|
:style="getColumnStyle(col)"
|
|
:style="getColumnStyle(col)"
|
|
|
:class="{
|
|
:class="{
|
|
|
'fixed-column': col.fixed,
|
|
'fixed-column': col.fixed,
|
|
@@ -139,7 +152,12 @@ export default {
|
|
|
isPreviewing: false,
|
|
isPreviewing: false,
|
|
|
currentPage: 1,
|
|
currentPage: 1,
|
|
|
columnWidths: {},
|
|
columnWidths: {},
|
|
|
- tableWidth: 0
|
|
|
|
|
|
|
+ tableWidth: 0,
|
|
|
|
|
+
|
|
|
|
|
+ // 计算后的表头行数据
|
|
|
|
|
+ headerRows: [],
|
|
|
|
|
+ // 扁平化的字段配置
|
|
|
|
|
+ tableFields: []
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
computed: {
|
|
computed: {
|
|
@@ -174,6 +192,90 @@ export default {
|
|
|
window.removeEventListener('resize', this.calculateColumnWidths)
|
|
window.removeEventListener('resize', this.calculateColumnWidths)
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
|
|
|
+ // 处理表头配置,生成表头行数据和扁平字段
|
|
|
|
|
+ processHeaderConfig(headerConfig) {
|
|
|
|
|
+ // 1. 扁平化字段配置
|
|
|
|
|
+ this.flattenFields(headerConfig)
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 生成表头行数据
|
|
|
|
|
+ const maxDepth = this.getMaxDepth(headerConfig)
|
|
|
|
|
+ this.headerRows = Array(maxDepth).fill().map(() => [])
|
|
|
|
|
+
|
|
|
|
|
+ this.buildHeaderRows(headerConfig, 0, 0)
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 扁平化字段配置
|
|
|
|
|
+ flattenFields(config, parentPath = '') {
|
|
|
|
|
+ config.forEach(item => {
|
|
|
|
|
+ if (item.prop) {
|
|
|
|
|
+ this.tableFields.push({
|
|
|
|
|
+ prop: item.prop,
|
|
|
|
|
+ label: item.label,
|
|
|
|
|
+ width: item.width
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (item.children) {
|
|
|
|
|
+ this.flattenFields(item.children, parentPath + item.label + '/')
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 获取表头最大深度
|
|
|
|
|
+ getMaxDepth(config) {
|
|
|
|
|
+ let maxDepth = 1
|
|
|
|
|
+ config.forEach(item => {
|
|
|
|
|
+ if (item.children) {
|
|
|
|
|
+ const depth = 1 + this.getMaxDepth(item.children)
|
|
|
|
|
+ if (depth > maxDepth) {
|
|
|
|
|
+ maxDepth = depth
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ return maxDepth
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 构建表头行数据
|
|
|
|
|
+ buildHeaderRows(config, currentRow, currentCol) {
|
|
|
|
|
+ config.forEach(item => {
|
|
|
|
|
+ // 计算当前项跨越的行数和列数
|
|
|
|
|
+ const rowspan = item.rowspan || 1
|
|
|
|
|
+ const colspan = item.colspan || this.calculateColspan(item)
|
|
|
|
|
+
|
|
|
|
|
+ // 在当前行和后续行中添加表头单元格
|
|
|
|
|
+ for (let i = 0; i < rowspan; i++) {
|
|
|
|
|
+ if (currentRow + i < this.headerRows.length) {
|
|
|
|
|
+ if (i === 0) {
|
|
|
|
|
+ // 主单元格
|
|
|
|
|
+ this.headerRows[currentRow + i].push({
|
|
|
|
|
+ label: item.label,
|
|
|
|
|
+ rowspan,
|
|
|
|
|
+ colspan,
|
|
|
|
|
+ width: item.width
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 被合并的行,添加空单元格占位
|
|
|
|
|
+ this.headerRows[currentRow + i].push(null)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果有子项,递归处理
|
|
|
|
|
+ if (item.children) {
|
|
|
|
|
+ this.buildHeaderRows(item.children, currentRow + 1, currentCol)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ currentCol += colspan
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 计算列跨度
|
|
|
|
|
+ calculateColspan(item) {
|
|
|
|
|
+ if (item.children) {
|
|
|
|
|
+ return item.children.reduce((sum, child) => sum + this.calculateColspan(child), 0)
|
|
|
|
|
+ }
|
|
|
|
|
+ return 1
|
|
|
|
|
+ },
|
|
|
getColumnStyle(col) {
|
|
getColumnStyle(col) {
|
|
|
const style = {}
|
|
const style = {}
|
|
|
if (this.columnWidths[col.prop]) {
|
|
if (this.columnWidths[col.prop]) {
|
|
@@ -251,7 +353,6 @@ export default {
|
|
|
// landscape = isLandscape;
|
|
// landscape = isLandscape;
|
|
|
// }
|
|
// }
|
|
|
let landscape = isLandscape;
|
|
let landscape = isLandscape;
|
|
|
- console.log(landscape)
|
|
|
|
|
|
|
|
|
|
printWindow.document.open()
|
|
printWindow.document.open()
|
|
|
printWindow.document.write(`
|
|
printWindow.document.write(`
|
|
@@ -366,6 +467,14 @@ export default {
|
|
|
this.$nextTick(() => {
|
|
this.$nextTick(() => {
|
|
|
this.calculateColumnWidths()
|
|
this.calculateColumnWidths()
|
|
|
})
|
|
})
|
|
|
|
|
+ },
|
|
|
|
|
+ columns: {
|
|
|
|
|
+ handler(newVal) {
|
|
|
|
|
+ this.tableFields = [];
|
|
|
|
|
+ this.processHeaderConfig(newVal);
|
|
|
|
|
+ },
|
|
|
|
|
+ deep: true,
|
|
|
|
|
+ immediate: true
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|