import { defineComponent, ref, reactive, computed, onMounted, watch } from 'vue'
|
import type { PropType } from 'vue'
|
import styles from './CanvasTableS2.module.scss'
|
import { PivotSheet, S2DataConfig, TableSheet, type S2Options } from '@antv/s2'
|
import { _t } from '@/libs/Language/Language'
|
|
export default defineComponent({
|
name: 'CanvasTableS2',
|
props: {
|
tableHeader: {
|
type: Array as PropType<any[]>,
|
required: true,
|
},
|
dataList: {
|
type: Array as PropType<any[]>,
|
required: true,
|
},
|
fixedColumn: {
|
type: Number,
|
default: 0,
|
},
|
saveConfig: {
|
type: Function,
|
default: () => {},
|
},
|
isExtendedSummaryTable: {
|
type: Boolean,
|
default: false,
|
},
|
summaryDataStructure: {
|
type: Array as PropType<any[]>,
|
default: () => [],
|
},
|
tableColumns: {
|
type: Array as PropType<any[]>,
|
default: () => [],
|
},
|
onSortChange: {
|
type: Function,
|
default: () => {},
|
},
|
},
|
setup(props, { emit, slots, expose }) {
|
const tableRef = ref<HTMLDivElement>()
|
const tableHeight = ref(0)
|
const tableWidth = ref(0)
|
|
/**
|
* 处理扩展总表和总表和原数据
|
*/
|
const data = computed(() => {
|
return props.dataList
|
})
|
|
const findSeq = (structure: any[], seq: string) => {
|
return structure.find((item) => {
|
return Object.entries(item).find(([key, value]) => {
|
if (key === 'Seq' && value[0].data) {
|
return value[0].data == seq
|
}
|
})
|
})
|
}
|
|
const summaryDataStructureComputed = computed(() => {
|
const structure = props.summaryDataStructure
|
const data = props.dataList
|
const result = []
|
data.forEach((item, index: number) => {
|
if (!Object.keys(structure).length) return
|
const findSeqItem = findSeq(structure, item.Seq)
|
// 需要判断seq是否存在,如果存在,将item设置为{}
|
if (findSeqItem) {
|
if (result.find((resultItem) => resultItem.seq == item.Seq)) {
|
result.push({
|
item: {},
|
seq: item.Seq,
|
})
|
} else {
|
result.push({
|
item: findSeqItem,
|
seq: item.Seq,
|
})
|
}
|
}
|
})
|
|
return result.map((item) => {
|
if (item.item) {
|
return item.item
|
} else {
|
return {}
|
}
|
})
|
})
|
|
/**
|
* 合并单元格
|
*/
|
const mergeCells = computed<any>(() => {
|
const mergeCells = []
|
// if (!props.isExtendedSummaryTable) {
|
// return mergeCells
|
// }
|
const mergeCellsMap = {}
|
const mergeCellArr = []
|
summaryDataStructureComputed.value.forEach((item, index: number) => {
|
Object.entries(item).forEach(([key, arr]: [string, any[]]) => {
|
const column = columnMap.value[key]
|
arr.forEach((row, i) => {
|
// mergeCellsMap[column?.index] = mergeCellsMap[column?.index] || []
|
// mergeCellsMap[column?.index].push({
|
// colIndex: column?.index,
|
// rowIndex: index + row.rowSpan,
|
// showText: false,
|
// })
|
mergeCells.push({
|
row: index,
|
col: column?.index,
|
rowspan: row.rowSpan,
|
colspan: 1,
|
key: key,
|
name: column?.name,
|
})
|
})
|
})
|
})
|
const filterMergeCells = mergeCells.filter(
|
(item) =>
|
(item.rowspan > 1 || item.colspan > 1) && item.col !== undefined
|
)
|
filterMergeCells.forEach((item) => {
|
const cells = []
|
if (item.rowspan > 1) {
|
for (let index = 0; index < item.rowspan; index++) {
|
cells.push({
|
colIndex: item.col,
|
rowIndex: item.row + index,
|
showText: index == 0 ? true : false,
|
})
|
}
|
}
|
if (cells.length) {
|
mergeCellArr.push(cells)
|
}
|
})
|
// console.log(mergeCellArr, 'mergeCellArr')
|
// Object.values(mergeCellsMap).forEach((arr: any[]) => {
|
// arr.forEach((item,index) => {
|
// if(index == 0) {
|
// item.showText = true
|
// item.
|
// } else {
|
|
// }
|
// })
|
// })
|
|
return mergeCellArr
|
})
|
|
const columnMap = computed(() => {
|
const map = {}
|
props.tableColumns.forEach((item, index) => {
|
map[item.key] = {
|
...item,
|
index: index,
|
}
|
})
|
return map
|
})
|
/**
|
* 表头数据
|
*/
|
const columns = computed(() => {
|
return props.tableHeader.map((item) => {
|
return {
|
title: item.name,
|
field: item.key,
|
name: item.name,
|
width: item.width,
|
children: item.childs.map((child) => {
|
return {
|
title: child.name,
|
name: child.name,
|
field: child.key,
|
width: child.width,
|
}
|
}),
|
}
|
})
|
})
|
|
watch(
|
() => props.dataList,
|
() => {
|
if (Array.isArray(props.dataList) && data.value.length) {
|
tableHeight.value = tableRef.value?.clientHeight
|
tableWidth.value = tableRef.value?.clientWidth
|
if (tableWidth.value && tableHeight.value) {
|
render(tableWidth.value, tableHeight.value)
|
}
|
}
|
}
|
)
|
|
const render = async (width, height) => {
|
const filedWidthMap = {}
|
props.tableColumns.forEach((column) => {
|
filedWidthMap[column.key] = column.width || 200
|
})
|
const s2Options: S2Options = {
|
width,
|
height,
|
hierarchyType: 'grid',
|
mergedCellsInfo: mergeCells.value,
|
style: {
|
colCell: {
|
widthByField: filedWidthMap,
|
},
|
},
|
// 提高滚动性能
|
transformCanvasConfig(renderer) {
|
renderer.setConfig({
|
enableCulling: true,
|
enableRenderingOptimization: true,
|
})
|
},
|
}
|
const s2DataConfig: S2DataConfig = {
|
fields: {
|
columns: columns.value,
|
},
|
data: data.value,
|
}
|
const container = document.querySelector('#s2_table')
|
|
const s2 = new TableSheet(container, s2DataConfig, s2Options)
|
s2.setTheme({
|
dataCell: {
|
bolderText: {
|
textAlign: 'center',
|
textBaseline: 'middle',
|
},
|
text: {
|
textAlign: 'center',
|
textBaseline: 'middle',
|
},
|
},
|
})
|
await s2.render()
|
}
|
// onMounted(async () => {
|
// // 获取表格的高度
|
// const t = setTimeout(() => {
|
// tableHeight.value = tableRef.value?.clientHeight
|
// tableWidth.value = tableRef.value?.clientWidth
|
// render(tableWidth.value, tableHeight.value)
|
// clearTimeout(t)
|
// }, 0)
|
// })
|
return () => {
|
return (
|
<div
|
class={styles.extendedSummaryTable}
|
id="s2_table"
|
ref={tableRef}
|
></div>
|
)
|
}
|
},
|
})
|