✨(component): 新增 table 复杂表头实现
This commit is contained in:
		
							parent
							
								
									8c9078b0fc
								
							
						
					
					
						commit
						db1c78f458
					
				@ -465,11 +465,6 @@
 | 
			
		||||
  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 {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  z-index: 890;
 | 
			
		||||
 | 
			
		||||
@ -91,53 +91,101 @@ const hasChecked = ref(false);
 | 
			
		||||
const tableDataSource = ref<any[]>([...props.dataSource]);
 | 
			
		||||
const tableColumns = computed(() => {
 | 
			
		||||
  return [...props.columns];
 | 
			
		||||
})
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const tableHeadColumns = ref<any[]>([])
 | 
			
		||||
const tableBodyColumns = ref<any[]>([])
 | 
			
		||||
const tableHeadColumns = 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[]) => {
 | 
			
		||||
  columns.forEach((column) => {
 | 
			
		||||
    if(column.children) {
 | 
			
		||||
    if (column.children) {
 | 
			
		||||
      findFindNode(column.children);
 | 
			
		||||
    } else {
 | 
			
		||||
      tableBodyColumns.value.push(column);
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
findFindNode(tableColumns.value)
 | 
			
		||||
findFindNode(tableColumns.value);
 | 
			
		||||
 | 
			
		||||
const tableColumnKeys = ref<any[]>([]);
 | 
			
		||||
 | 
			
		||||
const findFindNodes = (columns: any[]) => {
 | 
			
		||||
  columns.forEach((column) => {
 | 
			
		||||
    if(column.children) {
 | 
			
		||||
    if (column.children) {
 | 
			
		||||
      findFindNodes(column.children);
 | 
			
		||||
    } else {
 | 
			
		||||
      if(!column.hide) {
 | 
			
		||||
      if (!column.hide) {
 | 
			
		||||
        tableColumnKeys.value.push(column.key);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
findFindNodes(tableColumns.value)
 | 
			
		||||
findFindNodes(tableColumns.value);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 处理为复杂表头, 待完成
 | 
			
		||||
 * 
 | 
			
		||||
 * @param level 层级, 用于决定会被 push 到的目标数组 
 | 
			
		||||
 *
 | 
			
		||||
 * @param level 层级, 用于决定会被 push 到的目标数组
 | 
			
		||||
 */
 | 
			
		||||
const findFinalNode = (level: number, columns: any[]) => {
 | 
			
		||||
  columns.forEach(column => {
 | 
			
		||||
    if(column.children) {
 | 
			
		||||
     // 设置 rowspan 
 | 
			
		||||
  columns.forEach((column) => {
 | 
			
		||||
    if (column.children) {
 | 
			
		||||
      // 设置 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 {
 | 
			
		||||
     // 设置 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 tableExpandKeys = ref<Recordable[]>([...props.expandKeys]);
 | 
			
		||||
@ -538,71 +586,80 @@ const renderTotalRowCell = (column: any) => {
 | 
			
		||||
                </template>
 | 
			
		||||
              </colgroup>
 | 
			
		||||
              <thead>
 | 
			
		||||
                <tr>
 | 
			
		||||
                  <template
 | 
			
		||||
                    v-for="(column, columnIndex) in columns"
 | 
			
		||||
                    :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-for="(tableHeadColumn, tableHeadColumnIndex) in tableHeadColumns" :key="tableHeadColumnIndex">
 | 
			
		||||
                  <tr>
 | 
			
		||||
                    <template
 | 
			
		||||
                      v-for="(column, columnIndex) in tableHeadColumn"
 | 
			
		||||
                      :key="column"
 | 
			
		||||
                    >
 | 
			
		||||
                      <template v-if="column.type == 'checkbox'">
 | 
			
		||||
                        <lay-checkbox
 | 
			
		||||
                          v-model="hasChecked"
 | 
			
		||||
                          :is-indeterminate="!allChecked"
 | 
			
		||||
                          skin="primary"
 | 
			
		||||
                          value="all"
 | 
			
		||||
                          @change="changeAll"
 | 
			
		||||
                        />
 | 
			
		||||
                      </template>
 | 
			
		||||
                      <template v-else>
 | 
			
		||||
                        <span>
 | 
			
		||||
                          <template v-if="column.titleSlot">
 | 
			
		||||
                            <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>
 | 
			
		||||
                      <th
 | 
			
		||||
                        :colspan="column.colspan"
 | 
			
		||||
                        :rowspan="column.rowspan"
 | 
			
		||||
                        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'">
 | 
			
		||||
                          <lay-checkbox
 | 
			
		||||
                            v-model="hasChecked"
 | 
			
		||||
                            :is-indeterminate="!allChecked"
 | 
			
		||||
                            skin="primary"
 | 
			
		||||
                            value="all"
 | 
			
		||||
                            @change="changeAll"
 | 
			
		||||
                          />
 | 
			
		||||
                        </template>
 | 
			
		||||
                        <template v-else>
 | 
			
		||||
                          <span>
 | 
			
		||||
                            <template v-if="column.titleSlot">
 | 
			
		||||
                              <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>
 | 
			
		||||
            </table>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
@ -1169,7 +1169,7 @@ export default {
 | 
			
		||||
::: demo 通过 `span-method` 属性, 自定义行列合并的逻辑。
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <lay-table :columns="columns27" :data-source="dataSource27"></lay-table>
 | 
			
		||||
  <lay-table :columns="columns29" :data-source="dataSource29"></lay-table>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
@ -1178,7 +1178,7 @@ import { ref } from 'vue'
 | 
			
		||||
export default {
 | 
			
		||||
  setup() {
 | 
			
		||||
 | 
			
		||||
    const columns27 = [
 | 
			
		||||
    const columns29 = [
 | 
			
		||||
      {
 | 
			
		||||
        title:"名称",
 | 
			
		||||
        width:"200px",
 | 
			
		||||
@ -1188,6 +1188,7 @@ export default {
 | 
			
		||||
        children: [
 | 
			
		||||
          { title: "省", key: "province", width: "300px", },
 | 
			
		||||
          { title: "市", key: "city", width: "300px", },
 | 
			
		||||
          { title: "区", key: "area", width: "300px", },
 | 
			
		||||
        ]
 | 
			
		||||
      },{
 | 
			
		||||
        title:"性别",
 | 
			
		||||
@ -1204,17 +1205,17 @@ export default {
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    const dataSource27 = [
 | 
			
		||||
      {id:"1",username:"root",province:"山东",city:"济南", 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:"3",username:"woow",province:"山东",city:"济南", 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:"5",username:"woow",province:"山东",city:"济南", password:"woow",sex:"男", age:"20", remark: 'layui - vue(谐音:类 UI) '}
 | 
			
		||||
    const dataSource29 = [
 | 
			
		||||
      {id:"1",username:"就眠儀式",province:"山东",city:"济南",area: "高新区", 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:"就眠儀式",province:"山东",city:"济南",area: "高新区", 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:"就眠儀式",province:"山东",city:"济南",area: "高新区", password:"woow",sex:"男", age:"20", remark: 'layui - vue(谐音:类 UI) '}
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      columns27,
 | 
			
		||||
      dataSource27,
 | 
			
		||||
      columns29,
 | 
			
		||||
      dataSource29,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user