(component): 新增 table 复杂表头实现

This commit is contained in:
就眠儀式 2022-08-08 03:19:11 +08:00
parent 8c9078b0fc
commit db1c78f458
3 changed files with 152 additions and 99 deletions

View File

@ -465,11 +465,6 @@
box-shadow: inset -10px 0 8px -8px #00000026; box-shadow: inset -10px 0 8px -8px #00000026;
} }
.layui-table-view .layui-table tr th:last-child,
.layui-table-view .layui-table tr td:last-child {
border-right: none !important;
}
.layui-table-tool { .layui-table-tool {
position: relative; position: relative;
z-index: 890; z-index: 890;

View File

@ -91,38 +91,69 @@ const hasChecked = ref(false);
const tableDataSource = ref<any[]>([...props.dataSource]); const tableDataSource = ref<any[]>([...props.dataSource]);
const tableColumns = computed(() => { const tableColumns = computed(() => {
return [...props.columns]; return [...props.columns];
}) });
const tableHeadColumns = ref<any[]>([]) const tableHeadColumns = ref<any[]>([]);
const tableBodyColumns = ref<any[]>([]) const tableBodyColumns = ref<any[]>([]);
const getLevel = (arr: any[]) => {
let maxLevel = 0;
(function callBack(arr, level) {
++level;
maxLevel = Math.max(level, maxLevel);
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (item.children && item.children.length > 0) {
callBack(item.children, level);
} else {
delete item.children;
}
}
})(arr, 0);
return maxLevel;
};
function getLeafCountTree(json: any) {
if (!json.children || json.children.length == 0) {
json.colspan = 1;
return 1;
} else {
var leafCount = 0;
for (var i = 0; i < json.children.length; i++) {
leafCount = leafCount + getLeafCountTree(json.children[i]);
}
json.colspan = leafCount;
return leafCount;
}
}
const findFindNode = (columns: any[]) => { const findFindNode = (columns: any[]) => {
columns.forEach((column) => { columns.forEach((column) => {
if(column.children) { if (column.children) {
findFindNode(column.children); findFindNode(column.children);
} else { } else {
tableBodyColumns.value.push(column); tableBodyColumns.value.push(column);
} }
}) });
} };
findFindNode(tableColumns.value) findFindNode(tableColumns.value);
const tableColumnKeys = ref<any[]>([]); const tableColumnKeys = ref<any[]>([]);
const findFindNodes = (columns: any[]) => { const findFindNodes = (columns: any[]) => {
columns.forEach((column) => { columns.forEach((column) => {
if(column.children) { if (column.children) {
findFindNodes(column.children); findFindNodes(column.children);
} else { } else {
if(!column.hide) { if (!column.hide) {
tableColumnKeys.value.push(column.key); tableColumnKeys.value.push(column.key);
} }
} }
}) });
} };
findFindNodes(tableColumns.value) findFindNodes(tableColumns.value);
/** /**
* 处理为复杂表头, 待完成 * 处理为复杂表头, 待完成
@ -130,14 +161,31 @@ findFindNodes(tableColumns.value)
* @param level 层级, 用于决定会被 push 到的目标数组 * @param level 层级, 用于决定会被 push 到的目标数组
*/ */
const findFinalNode = (level: number, columns: any[]) => { const findFinalNode = (level: number, columns: any[]) => {
columns.forEach(column => { columns.forEach((column) => {
if(column.children) { if (column.children) {
// rowspan // colspan
const colSpan = getLeafCountTree(column);
column.colspan = colSpan;
column.rowspan = 1;
if (!tableHeadColumns.value[level]) {
tableHeadColumns.value[level] = [];
}
tableHeadColumns.value[level].push(column);
findFinalNode(level + 1, column.children);
} else { } else {
// colspan // rowspan
const rowSpan = getLevel(columns);
column.rowspan = rowSpan;
column.colspan = 1;
if (!tableHeadColumns.value[level]) {
tableHeadColumns.value[level] = [];
}
tableHeadColumns.value[level].push(column);
} }
}) });
} };
findFinalNode(0, tableColumns.value);
const tableSelectedKeys = ref<Recordable[]>([...props.selectedKeys]); const tableSelectedKeys = ref<Recordable[]>([...props.selectedKeys]);
const tableExpandKeys = ref<Recordable[]>([...props.expandKeys]); const tableExpandKeys = ref<Recordable[]>([...props.expandKeys]);
@ -538,71 +586,80 @@ const renderTotalRowCell = (column: any) => {
</template> </template>
</colgroup> </colgroup>
<thead> <thead>
<tr> <template v-for="(tableHeadColumn, tableHeadColumnIndex) in tableHeadColumns" :key="tableHeadColumnIndex">
<template <tr>
v-for="(column, columnIndex) in columns" <template
:key="column" v-for="(column, columnIndex) in tableHeadColumn"
> :key="column"
<th
v-if="tableColumnKeys.includes(column.key)"
class="layui-table-cell"
:class="[
renderFixedClassName(column, columnIndex),
column.fixed ? `layui-table-fixed-${column.fixed}` : '',
column.type == 'checkbox'
? 'layui-table-cell-checkbox'
: '',
column.type == 'radio' ? 'layui-table-cell-radio' : '',
column.type == 'number'
? 'layui-table-cell-number'
: '',
]"
:style="[
{
textAlign: column.align,
},
renderFixedStyle(column, columnIndex),
]"
> >
<template v-if="column.type == 'checkbox'"> <th
<lay-checkbox :colspan="column.colspan"
v-model="hasChecked" :rowspan="column.rowspan"
:is-indeterminate="!allChecked" class="layui-table-cell"
skin="primary" :class="[
value="all" renderFixedClassName(column, columnIndex),
@change="changeAll" column.fixed
/> ? `layui-table-fixed-${column.fixed}`
</template> : '',
<template v-else> column.type == 'checkbox'
<span> ? 'layui-table-cell-checkbox'
<template v-if="column.titleSlot"> : '',
<slot :name="column.titleSlot"></slot> column.type == 'radio'
</template> ? 'layui-table-cell-radio'
<template v-else> : '',
{{ column.title }} column.type == 'number'
</template> ? 'layui-table-cell-number'
</span> : '',
<!-- 插槽 --> ]"
<span :style="[
v-if="column.sort" {
class="layui-table-sort layui-inline" textAlign: column.align,
lay-sort },
> renderFixedStyle(column, columnIndex),
<i ]"
@click.stop="sortTable($event, column.key, 'asc')" >
class="layui-edge layui-table-sort-asc" <template v-if="column.type == 'checkbox'">
title="升序" <lay-checkbox
></i> v-model="hasChecked"
<i :is-indeterminate="!allChecked"
@click.stop="sortTable($event, column.key, 'desc')" skin="primary"
class="layui-edge layui-table-sort-desc" value="all"
title="降序" @change="changeAll"
></i> />
</span> </template>
</template> <template v-else>
</th> <span>
</template> <template v-if="column.titleSlot">
</tr> <slot :name="column.titleSlot"></slot>
</template>
<template v-else>
{{ column.title }}
</template>
</span>
<!-- 插槽 -->
<span
v-if="column.sort"
class="layui-table-sort layui-inline"
lay-sort
>
<i
@click.stop="sortTable($event, column.key, 'asc')"
class="layui-edge layui-table-sort-asc"
title="升序"
></i>
<i
@click.stop="
sortTable($event, column.key, 'desc')
"
class="layui-edge layui-table-sort-desc"
title="降序"
></i>
</span>
</template>
</th>
</template>
</tr>
</template>
</thead> </thead>
</table> </table>
</div> </div>

View File

@ -1169,7 +1169,7 @@ export default {
::: demo 通过 `span-method` 属性, 自定义行列合并的逻辑。 ::: demo 通过 `span-method` 属性, 自定义行列合并的逻辑。
<template> <template>
<lay-table :columns="columns27" :data-source="dataSource27"></lay-table> <lay-table :columns="columns29" :data-source="dataSource29"></lay-table>
</template> </template>
<script> <script>
@ -1178,7 +1178,7 @@ import { ref } from 'vue'
export default { export default {
setup() { setup() {
const columns27 = [ const columns29 = [
{ {
title:"名称", title:"名称",
width:"200px", width:"200px",
@ -1188,6 +1188,7 @@ export default {
children: [ children: [
{ title: "省", key: "province", width: "300px", }, { title: "省", key: "province", width: "300px", },
{ title: "市", key: "city", width: "300px", }, { title: "市", key: "city", width: "300px", },
{ title: "区", key: "area", width: "300px", },
] ]
},{ },{
title:"性别", title:"性别",
@ -1204,17 +1205,17 @@ export default {
} }
] ]
const dataSource27 = [ const dataSource29 = [
{id:"1",username:"root",province:"山东",city:"济南", password:"root",sex:"男", age:"18", remark: 'layui - vue谐音类 UI) '}, {id:"1",username:"就眠儀式",province:"山东",city:"济南",area: "高新区", password:"root",sex:"男", age:"18", remark: 'layui - vue谐音类 UI) '},
{id:"2",username:"root",province:"山东",city:"济南", password:"root",sex:"男", age:"18", remark: 'layui - vue谐音类 UI) '}, {id:"2",username:"就眠儀式",province:"山东",city:"济南",area: "高新区", password:"root",sex:"男", age:"18", remark: 'layui - vue谐音类 UI) '},
{id:"3",username:"woow",province:"山东",city:"济南", password:"woow",sex:"男", age:"20", remark: 'layui - vue谐音类 UI) '}, {id:"3",username:"就眠儀式",province:"山东",city:"济南",area: "高新区", password:"woow",sex:"男", age:"20", remark: 'layui - vue谐音类 UI) '},
{id:"4",username:"woow",province:"山东",city:"济南", password:"woow",sex:"男", age:"20", remark: 'layui - vue谐音类 UI) '}, {id:"4",username:"就眠儀式",province:"山东",city:"济南",area: "高新区", password:"woow",sex:"男", age:"20", remark: 'layui - vue谐音类 UI) '},
{id:"5",username:"woow",province:"山东",city:"济南", password:"woow",sex:"男", age:"20", remark: 'layui - vue谐音类 UI) '} {id:"5",username:"就眠儀式",province:"山东",city:"济南",area: "高新区", password:"woow",sex:"男", age:"20", remark: 'layui - vue谐音类 UI) '}
] ]
return { return {
columns27, columns29,
dataSource27, dataSource29,
} }
} }
} }