|
@@ -2,6 +2,7 @@
|
|
|
import symbolKeys from "@@@/table/symbol"
|
|
import symbolKeys from "@@@/table/symbol"
|
|
|
import VbTr from "@@@/table/partials/header/HeaderTr.vue"
|
|
import VbTr from "@@@/table/partials/header/HeaderTr.vue"
|
|
|
import type { Sort, Header, HeaderEx } from "@@@/table/models"
|
|
import type { Sort, Header, HeaderEx } from "@@@/table/models"
|
|
|
|
|
+
|
|
|
const propOpts = inject(symbolKeys.header, {
|
|
const propOpts = inject(symbolKeys.header, {
|
|
|
columns: ref([]),
|
|
columns: ref([]),
|
|
|
hasCheckbox: true,
|
|
hasCheckbox: true,
|
|
@@ -15,66 +16,102 @@ const { columns } = propOpts
|
|
|
|
|
|
|
|
const sort = ref<Sort>({
|
|
const sort = ref<Sort>({
|
|
|
label: propOpts.sortField,
|
|
label: propOpts.sortField,
|
|
|
- order: propOpts.sortOrder
|
|
|
|
|
|
|
+ order: propOpts.sortOrder as "asc" | "desc"
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
const columnList = ref<HeaderEx[][]>([])
|
|
const columnList = ref<HeaderEx[][]>([])
|
|
|
|
|
+const headerColumns = ref<HeaderEx[][]>([])
|
|
|
const rowspan = computed(() => {
|
|
const rowspan = computed(() => {
|
|
|
return columnList.value.length
|
|
return columnList.value.length
|
|
|
})
|
|
})
|
|
|
-const convert = (headers: Header[], deep: number): HeaderEx[] => {
|
|
|
|
|
- if (!columnList.value[deep]) {
|
|
|
|
|
- columnList.value.push([])
|
|
|
|
|
- }
|
|
|
|
|
- const list = columnList.value[deep]
|
|
|
|
|
- const selfChildren = [] as HeaderEx[]
|
|
|
|
|
- headers.forEach((v) => {
|
|
|
|
|
- if (
|
|
|
|
|
- v.visible == false ||
|
|
|
|
|
- (v.children && v.children.find((v) => v.visible == undefined || v.visible) == null)
|
|
|
|
|
- ) {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
- const item = Object.assign({}, v, {
|
|
|
|
|
- rowspan: (rs: number) => rs - deep,
|
|
|
|
|
- colspan: v.children?.length ?? 1,
|
|
|
|
|
- children: [] as HeaderEx[]
|
|
|
|
|
- }) as HeaderEx
|
|
|
|
|
- if (v.children) {
|
|
|
|
|
- delete item.isSort
|
|
|
|
|
- item.rowspan = 1
|
|
|
|
|
- const _children = convert(v.children, deep + 1)
|
|
|
|
|
- item.children = _children
|
|
|
|
|
|
|
+
|
|
|
|
|
+const convert = (headers: Header[], deep: number): HeaderEx[][] => {
|
|
|
|
|
+ const allLists: HeaderEx[][] = []
|
|
|
|
|
+
|
|
|
|
|
+ const recursion = (h: Header[], d: number): HeaderEx[] => {
|
|
|
|
|
+ if (!allLists[d]) {
|
|
|
|
|
+ allLists[d] = []
|
|
|
}
|
|
}
|
|
|
- selfChildren.push(item)
|
|
|
|
|
- list.push(item)
|
|
|
|
|
- })
|
|
|
|
|
- list.forEach((v) => {
|
|
|
|
|
- //v.rowspan = v.rowspan != 1 ? (rs: number) => rs - deep : 1
|
|
|
|
|
- v.colspan = v.colspan != 1 ? caclColspan(v.children) : 1
|
|
|
|
|
- })
|
|
|
|
|
- return selfChildren
|
|
|
|
|
- function caclColspan(v?: HeaderEx[]): number {
|
|
|
|
|
- let colspan = 0
|
|
|
|
|
- if (v?.length) {
|
|
|
|
|
- v.forEach((vv) => {
|
|
|
|
|
- colspan += vv.children && vv.children.length ? caclColspan(vv.children) : vv.colspan
|
|
|
|
|
|
|
+ const currentLevelList = allLists[d]
|
|
|
|
|
+ const currentChildren: HeaderEx[] = []
|
|
|
|
|
+
|
|
|
|
|
+ h.forEach((v) => {
|
|
|
|
|
+ if (
|
|
|
|
|
+ v.visible === false ||
|
|
|
|
|
+ (v.children && v.children.every((child) => child.visible === false))
|
|
|
|
|
+ ) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const item: HeaderEx = Object.assign({}, v, {
|
|
|
|
|
+ rowspan: (rs: number) => rs - d,
|
|
|
|
|
+ colspan: v.children?.length ?? 1,
|
|
|
|
|
+ children: [] as HeaderEx[]
|
|
|
})
|
|
})
|
|
|
|
|
+
|
|
|
|
|
+ // 处理有子级的列:行合并为1,递归处理子级
|
|
|
|
|
+ if (v.children && v.children.length > 0) {
|
|
|
|
|
+ delete item.isSort
|
|
|
|
|
+ item.rowspan = 1 // 有子级的列,自身行合并为1
|
|
|
|
|
+ const childItems = recursion(v.children, d + 1)
|
|
|
|
|
+ item.children = childItems
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ currentChildren.push(item)
|
|
|
|
|
+ currentLevelList.push(item)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ const calcColspan = (children?: HeaderEx[]): number => {
|
|
|
|
|
+ let totalColspan = 0
|
|
|
|
|
+ if (!children || children.length === 0) return totalColspan
|
|
|
|
|
+ children.forEach((child) => {
|
|
|
|
|
+ totalColspan +=
|
|
|
|
|
+ child.children && child.children.length > 0 ? calcColspan(child.children) : child.colspan
|
|
|
|
|
+ })
|
|
|
|
|
+ return totalColspan
|
|
|
}
|
|
}
|
|
|
- return colspan
|
|
|
|
|
|
|
+
|
|
|
|
|
+ currentLevelList.forEach((item) => {
|
|
|
|
|
+ if (item.children && item.children.length > 0) {
|
|
|
|
|
+ item.colspan = calcColspan(item.children) // 子级列数求和作为当前列colspan
|
|
|
|
|
+ } else {
|
|
|
|
|
+ item.colspan = 1 // 无子级的列,列合并为1
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ return currentChildren
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ recursion(headers, deep)
|
|
|
|
|
+ return allLists
|
|
|
}
|
|
}
|
|
|
-const headerColumns = computed(() => {
|
|
|
|
|
- columnList.value = []
|
|
|
|
|
- if (columns.value.filter((v) => v.children && v.children.length > 0).length > 0) {
|
|
|
|
|
- convert(columns.value, 0)
|
|
|
|
|
- } else {
|
|
|
|
|
- columnList.value.push(
|
|
|
|
|
- columns.value.filter((v) => v.visible == undefined || v.visible) as HeaderEx[]
|
|
|
|
|
- )
|
|
|
|
|
|
|
+
|
|
|
|
|
+watch(
|
|
|
|
|
+ () => columns.value,
|
|
|
|
|
+ async () => {
|
|
|
|
|
+ await nextTick() // 等待DOM更新,确保计算准确
|
|
|
|
|
+ columnList.value = []
|
|
|
|
|
+ headerColumns.value = []
|
|
|
|
|
+
|
|
|
|
|
+ if (columns.value.some((v) => v.children && v.children.length > 0)) {
|
|
|
|
|
+ const convertedLists = convert(columns.value, 0)
|
|
|
|
|
+ columnList.value = convertedLists
|
|
|
|
|
+ headerColumns.value = convertedLists
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const flatColumns = columns.value.filter((v) => v.visible !== false) as HeaderEx[]
|
|
|
|
|
+ flatColumns.forEach((item) => {
|
|
|
|
|
+ item.rowspan = rowspan.value
|
|
|
|
|
+ item.colspan = 1
|
|
|
|
|
+ })
|
|
|
|
|
+ columnList.value = [flatColumns]
|
|
|
|
|
+ headerColumns.value = [flatColumns]
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ immediate: true, // 初始化执行一次
|
|
|
|
|
+ deep: true // 深度监听columns(包括children变化)
|
|
|
}
|
|
}
|
|
|
- return columnList.value
|
|
|
|
|
-})
|
|
|
|
|
|
|
+)
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
|
<template>
|
|
@@ -84,7 +121,7 @@ const headerColumns = computed(() => {
|
|
|
:rowspan="rowspan"
|
|
:rowspan="rowspan"
|
|
|
:columns="v"
|
|
:columns="v"
|
|
|
:sort="sort"
|
|
:sort="sort"
|
|
|
- :has-checkbox="i == 0 && propOpts.hasCheckbox"
|
|
|
|
|
|
|
+ :has-checkbox="i === 0 && propOpts.hasCheckbox"
|
|
|
:is-multiple-check="propOpts.isMultipleCheck"
|
|
:is-multiple-check="propOpts.isMultipleCheck"
|
|
|
:th-tr-class="propOpts.thTrClass">
|
|
:th-tr-class="propOpts.thTrClass">
|
|
|
<template v-for="(_, name) in $slots" #[name]="{ row }">
|
|
<template v-for="(_, name) in $slots" #[name]="{ row }">
|