✨(table): add sub-table tree-table
This commit is contained in:
		
							parent
							
								
									1f5313fd94
								
							
						
					
					
						commit
						3e68cdf169
					
				
							
								
								
									
										183
									
								
								package/component/src/component/table/TableRow.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								package/component/src/component/table/TableRow.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,183 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
export default {
 | 
			
		||||
  name: "TableRow",
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { computed, ref, useSlots, WritableComputedRef } from "vue";
 | 
			
		||||
import { Recordable } from "../../types";
 | 
			
		||||
 | 
			
		||||
export interface LayTableProps {
 | 
			
		||||
  selectedKeys: Recordable[];
 | 
			
		||||
  tableColumnKeys: Recordable[];
 | 
			
		||||
  columns: Recordable[];
 | 
			
		||||
  checkbox?: boolean;
 | 
			
		||||
  id: string;
 | 
			
		||||
  data: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const slot = useSlots();
 | 
			
		||||
const emit = defineEmits([
 | 
			
		||||
  "row",
 | 
			
		||||
  "row-double",
 | 
			
		||||
  "contextmenu",
 | 
			
		||||
  "update:selectedKeys",
 | 
			
		||||
]);
 | 
			
		||||
 | 
			
		||||
const props = withDefaults(defineProps<LayTableProps>(), {
 | 
			
		||||
  checkbox: false,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const tableSelectedKeys: WritableComputedRef<Recordable[]> = computed({
 | 
			
		||||
  get() {
 | 
			
		||||
    return [...props.selectedKeys];
 | 
			
		||||
  },
 | 
			
		||||
  set(val) {
 | 
			
		||||
    emit("update:selectedKeys", val);
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const isExpand = ref(false);
 | 
			
		||||
const slotsData = ref<string[]>([]);
 | 
			
		||||
 | 
			
		||||
props.columns.map((value: any) => {
 | 
			
		||||
  if (value.customSlot) {
 | 
			
		||||
    slotsData.value.push(value.customSlot);
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const rowClick = function (data: any, evt: MouseEvent) {
 | 
			
		||||
  emit("row", data, evt);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const rowDoubleClick = function (data: any, evt: MouseEvent) {
 | 
			
		||||
  emit("row-double", data, evt);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const contextmenu = function (data: any, evt: MouseEvent) {
 | 
			
		||||
  emit("contextmenu", data, evt);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const expandIconType = computed(() => {
 | 
			
		||||
  return isExpand.value ? "layui-icon-subtraction" : "layui-icon-addition";
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const handleExpand = () => {
 | 
			
		||||
  isExpand.value = !isExpand.value;
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <tr
 | 
			
		||||
    @click.stop="rowClick(data, $event)"
 | 
			
		||||
    @dblclick.stop="rowDoubleClick(data, $event)"
 | 
			
		||||
    @contextmenu.stop="contextmenu(data, $event)"
 | 
			
		||||
  >
 | 
			
		||||
    <!-- 复选框 -->
 | 
			
		||||
    <td v-if="checkbox" class="layui-table-col-special">
 | 
			
		||||
      <div class="layui-table-cell laytable-cell-checkbox">
 | 
			
		||||
        <lay-checkbox
 | 
			
		||||
          v-model="tableSelectedKeys"
 | 
			
		||||
          :label="data[id]"
 | 
			
		||||
          skin="primary"
 | 
			
		||||
        />
 | 
			
		||||
      </div>
 | 
			
		||||
    </td>
 | 
			
		||||
 | 
			
		||||
    <!-- 数据列 -->
 | 
			
		||||
    <template v-for="(column, index) in columns" :key="column">
 | 
			
		||||
      <!-- 展示否 -->
 | 
			
		||||
      <template v-if="tableColumnKeys.includes(column.key)">
 | 
			
		||||
        <!-- 插槽列 -->
 | 
			
		||||
        <template v-if="column.customSlot">
 | 
			
		||||
          <td
 | 
			
		||||
            class="layui-table-cell"
 | 
			
		||||
            :style="{
 | 
			
		||||
              textAlign: column.align,
 | 
			
		||||
              width: column.width ? column.width : '0',
 | 
			
		||||
              minWidth: column.minWidth ? column.minWidth : '47px',
 | 
			
		||||
              whiteSpace: column.ellipsisTooltip ? 'nowrap' : 'normal',
 | 
			
		||||
            }"
 | 
			
		||||
          >
 | 
			
		||||
              <lay-icon
 | 
			
		||||
                v-if="(slot.expand || data.children) && index === 0"
 | 
			
		||||
                class="layui-table-cell-expand-icon"
 | 
			
		||||
                :type="expandIconType"
 | 
			
		||||
                @click="handleExpand"
 | 
			
		||||
              ></lay-icon>
 | 
			
		||||
 | 
			
		||||
            <lay-tooltip
 | 
			
		||||
              v-if="column.ellipsisTooltip"
 | 
			
		||||
              :content="data[column.key]"
 | 
			
		||||
              :isAutoShow="true"
 | 
			
		||||
            >
 | 
			
		||||
              <slot :name="column.customSlot" :data="data"></slot>
 | 
			
		||||
            </lay-tooltip>
 | 
			
		||||
            <slot v-else :name="column.customSlot" :data="data"></slot>
 | 
			
		||||
          </td>
 | 
			
		||||
        </template>
 | 
			
		||||
 | 
			
		||||
        <!-- 匹 配 Column -->
 | 
			
		||||
        <template v-else>
 | 
			
		||||
          <template v-if="column.key in data">
 | 
			
		||||
            <td
 | 
			
		||||
              class="layui-table-cell"
 | 
			
		||||
              :style="{
 | 
			
		||||
                textAlign: column.align,
 | 
			
		||||
                width: column.width ? column.width : '0',
 | 
			
		||||
                minWidth: column.minWidth ? column.minWidth : '47px',
 | 
			
		||||
                whiteSpace: column.ellipsisTooltip ? 'nowrap' : 'normal',
 | 
			
		||||
              }"
 | 
			
		||||
            >
 | 
			
		||||
              <lay-icon
 | 
			
		||||
                v-if="(slot.expand || data.children) && index === 0"
 | 
			
		||||
                class="layui-table-cell-expand-icon"
 | 
			
		||||
                :type="expandIconType"
 | 
			
		||||
                @click="handleExpand"
 | 
			
		||||
              ></lay-icon>
 | 
			
		||||
 | 
			
		||||
              <lay-tooltip
 | 
			
		||||
                v-if="column.ellipsisTooltip"
 | 
			
		||||
                :content="data[column.key]"
 | 
			
		||||
                :isAutoShow="true"
 | 
			
		||||
              >
 | 
			
		||||
                {{ data[column.key] }}
 | 
			
		||||
              </lay-tooltip>
 | 
			
		||||
              <span v-else> {{ data[column.key] }} </span>
 | 
			
		||||
            </td>
 | 
			
		||||
          </template>
 | 
			
		||||
        </template>
 | 
			
		||||
      </template>
 | 
			
		||||
    </template>
 | 
			
		||||
  </tr>
 | 
			
		||||
 | 
			
		||||
  <!-- 嵌套表单 -->
 | 
			
		||||
  <tr class="layui-table-cell-expand" v-if="slot.expand && isExpand">
 | 
			
		||||
    <slot name="expand"></slot>
 | 
			
		||||
  </tr>
 | 
			
		||||
 | 
			
		||||
  <!-- 树形结构 -->
 | 
			
		||||
  <template v-if="data.children && isExpand">
 | 
			
		||||
    <template v-for="(children, index) in data.children" :key="index">
 | 
			
		||||
      <table-row
 | 
			
		||||
        :id="id"
 | 
			
		||||
        :data="children"
 | 
			
		||||
        :columns="columns"
 | 
			
		||||
        :checkbox="checkbox"
 | 
			
		||||
        :tableColumnKeys="tableColumnKeys"
 | 
			
		||||
        @row="rowClick"
 | 
			
		||||
        @row-double="rowDoubleClick"
 | 
			
		||||
        @contextmenu="contextmenu"
 | 
			
		||||
        v-model:selectedKeys="tableSelectedKeys"
 | 
			
		||||
      >
 | 
			
		||||
        <template v-for="name in slotsData" #[name]>
 | 
			
		||||
          <slot :name="name" :data="data"></slot>
 | 
			
		||||
        </template>
 | 
			
		||||
        <template v-if="slot.expand" #expand>
 | 
			
		||||
          <slot name="expand" :data="data"></slot>
 | 
			
		||||
        </template>
 | 
			
		||||
      </table-row>
 | 
			
		||||
    </template>
 | 
			
		||||
  </template>
 | 
			
		||||
</template>
 | 
			
		||||
@ -12,10 +12,6 @@
 | 
			
		||||
  table-layout: fixed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.layui-table tr {
 | 
			
		||||
  // display: flex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.layui-table th {
 | 
			
		||||
  text-align: left;
 | 
			
		||||
  font-weight: 400;
 | 
			
		||||
@ -112,7 +108,7 @@
 | 
			
		||||
.layui-table-view .layui-table {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  border-collapse: separate;
 | 
			
		||||
  border-collapse: collapse;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.layui-table-view .layui-table[lay-skin="line"] {
 | 
			
		||||
@ -240,8 +236,8 @@
 | 
			
		||||
.layui-table-tool-panel li {
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
  // white-space: nowrap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.layui-table-call-ellipsis{
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
@ -360,6 +356,12 @@
 | 
			
		||||
  -webkit-box-pack: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.layui-table-cell-expand-icon {
 | 
			
		||||
  border: 1px solid #eee;
 | 
			
		||||
  margin-right: 8px;
 | 
			
		||||
  border-radius: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.layui-table-body {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
@ -370,7 +372,7 @@
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &::-webkit-scrollbar-thumb {
 | 
			
		||||
    background-color: rgba(0, 0, 0, 0.4);
 | 
			
		||||
    background-color: rgba(0, 0, 0, 0.2);
 | 
			
		||||
    background-clip: padding-box;
 | 
			
		||||
    border: 3px solid transparent;
 | 
			
		||||
    border-radius: 7px;
 | 
			
		||||
@ -635,3 +637,7 @@ body .layui-table-tips .layui-layer-content {
 | 
			
		||||
.layui-table-view {
 | 
			
		||||
  margin: 10px 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.layui-table-cell-expand{
 | 
			
		||||
  border-bottom: 1px solid #eee;
 | 
			
		||||
}
 | 
			
		||||
@ -6,7 +6,7 @@ export default {
 | 
			
		||||
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import "./index.less";
 | 
			
		||||
import { ref, watch, useSlots, withDefaults, onMounted } from "vue";
 | 
			
		||||
import { ref, watch, useSlots, withDefaults, onMounted, Ref } from "vue";
 | 
			
		||||
import { v4 as uuidv4 } from "../../utils/guidUtil";
 | 
			
		||||
import { Recordable } from "../../types";
 | 
			
		||||
import LayCheckbox from "../checkbox/index.vue";
 | 
			
		||||
@ -14,6 +14,7 @@ import LayDropdown from "../dropdown/index.vue";
 | 
			
		||||
import LayTooltip from "../tooltip/index.vue";
 | 
			
		||||
import { LayIcon } from "@layui/icons-vue";
 | 
			
		||||
import LayPage from "../page/index.vue";
 | 
			
		||||
import TableRow from "./TableRow.vue";
 | 
			
		||||
 | 
			
		||||
export interface LayTableProps {
 | 
			
		||||
  id?: string;
 | 
			
		||||
@ -49,7 +50,7 @@ const slots = slot.default && slot.default();
 | 
			
		||||
 | 
			
		||||
const allChecked = ref(false);
 | 
			
		||||
const tableDataSource = ref([...props.dataSource]);
 | 
			
		||||
const tableSelectedKeys = ref([...props.selectedKeys]);
 | 
			
		||||
const tableSelectedKeys = ref<Recordable[]>([...props.selectedKeys]);
 | 
			
		||||
const tableColumns = ref([...props.columns]);
 | 
			
		||||
const tableColumnKeys = ref(
 | 
			
		||||
  props.columns.map((item: any) => {
 | 
			
		||||
@ -81,7 +82,7 @@ const changeAll = function (checked: any) {
 | 
			
		||||
 | 
			
		||||
watch(
 | 
			
		||||
  tableSelectedKeys,
 | 
			
		||||
  function () {
 | 
			
		||||
  () => {
 | 
			
		||||
    if (tableSelectedKeys.value.length === props.dataSource.length) {
 | 
			
		||||
      allChecked.value = true;
 | 
			
		||||
    } else {
 | 
			
		||||
@ -108,7 +109,6 @@ const contextmenu = function (data: any, evt: MouseEvent) {
 | 
			
		||||
  emit("contextmenu", data, evt);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 打印 table 数据
 | 
			
		||||
const print = function () {
 | 
			
		||||
  let subOutputRankPrint = document.getElementById(tableId) as HTMLElement;
 | 
			
		||||
  let newContent = subOutputRankPrint.innerHTML;
 | 
			
		||||
@ -163,16 +163,12 @@ function exportToExcel(headerList: any, bodyList: any) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const sortTable = (e: any, key: string, sort: string) => {
 | 
			
		||||
  // 当前排序
 | 
			
		||||
  let currentSort = e.target.parentNode.getAttribute("lay-sort");
 | 
			
		||||
  // 点击排序
 | 
			
		||||
  if (sort === "desc") {
 | 
			
		||||
    if (currentSort === sort) {
 | 
			
		||||
      // 取消排序
 | 
			
		||||
      e.target.parentNode.setAttribute("lay-sort", "");
 | 
			
		||||
      tableDataSource.value = [...props.dataSource];
 | 
			
		||||
    } else {
 | 
			
		||||
      // 进行 desc 排序
 | 
			
		||||
      e.target.parentNode.setAttribute("lay-sort", "desc");
 | 
			
		||||
      tableDataSource.value.sort((x, y) => {
 | 
			
		||||
        if (x[key] < y[key]) return 1;
 | 
			
		||||
@ -182,11 +178,9 @@ const sortTable = (e: any, key: string, sort: string) => {
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    if (currentSort === sort) {
 | 
			
		||||
      // 取消排序
 | 
			
		||||
      e.target.parentNode.setAttribute("lay-sort", "");
 | 
			
		||||
      tableDataSource.value = [...props.dataSource];
 | 
			
		||||
    } else {
 | 
			
		||||
      // 进行 asc 排序
 | 
			
		||||
      e.target.parentNode.setAttribute("lay-sort", "asc");
 | 
			
		||||
      tableDataSource.value.sort((x, y) => {
 | 
			
		||||
        if (x[key] < y[key]) return -1;
 | 
			
		||||
@ -200,12 +194,19 @@ const sortTable = (e: any, key: string, sort: string) => {
 | 
			
		||||
let tableHeader = ref<HTMLElement | null>(null);
 | 
			
		||||
let tableBody = ref<HTMLElement | null>(null);
 | 
			
		||||
 | 
			
		||||
// 拖动监听
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  tableBody.value?.addEventListener("scroll", () => {
 | 
			
		||||
    tableHeader.value!.scrollLeft = tableBody.value?.scrollLeft || 0;
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const slotsData = ref<string[]>([]);
 | 
			
		||||
 | 
			
		||||
props.columns.map((value: any) => {
 | 
			
		||||
  if (value.customSlot) {
 | 
			
		||||
    slotsData.value.push(value.customSlot);
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
@ -315,86 +316,26 @@ onMounted(() => {
 | 
			
		||||
        <div class="layui-table-body layui-table-main" ref="tableBody">
 | 
			
		||||
          <table class="layui-table" :lay-size="size">
 | 
			
		||||
            <tbody>
 | 
			
		||||
              <!-- 渲染 -->
 | 
			
		||||
              <template v-for="data in tableDataSource" :key="data">
 | 
			
		||||
                <tr
 | 
			
		||||
                  @click.stop="rowClick(data, $event)"
 | 
			
		||||
                  @dblclick.stop="rowDoubleClick(data, $event)"
 | 
			
		||||
                  @contextmenu.stop="contextmenu(data, $event)"
 | 
			
		||||
                <table-row
 | 
			
		||||
                  :id="id"
 | 
			
		||||
                  :data="data"
 | 
			
		||||
                  :columns="columns"
 | 
			
		||||
                  :checkbox="checkbox"
 | 
			
		||||
                  :tableColumnKeys="tableColumnKeys"
 | 
			
		||||
                  @row="rowClick"
 | 
			
		||||
                  @row-double="rowDoubleClick"
 | 
			
		||||
                  @contextmenu="contextmenu"
 | 
			
		||||
                  v-model:selectedKeys="tableSelectedKeys"
 | 
			
		||||
                >
 | 
			
		||||
                  <!-- 复选框 -->
 | 
			
		||||
                  <td v-if="checkbox" class="layui-table-col-special">
 | 
			
		||||
                    <div class="layui-table-cell laytable-cell-checkbox">
 | 
			
		||||
                      <lay-checkbox
 | 
			
		||||
                        v-model="tableSelectedKeys"
 | 
			
		||||
                        skin="primary"
 | 
			
		||||
                        :label="data[id]"
 | 
			
		||||
                      />
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </td>
 | 
			
		||||
 | 
			
		||||
                  <!-- 数据列 -->
 | 
			
		||||
                  <template v-for="column in columns" :key="column">
 | 
			
		||||
                    <!-- 展示否 -->
 | 
			
		||||
                    <template v-if="tableColumnKeys.includes(column.key)">
 | 
			
		||||
                      <!-- 插槽列 -->
 | 
			
		||||
                      <template v-if="column.customSlot">
 | 
			
		||||
                        <td
 | 
			
		||||
                          class="layui-table-cell"
 | 
			
		||||
                          :style="{
 | 
			
		||||
                            textAlign: column.align,
 | 
			
		||||
                            width: column.width ? column.width : '0',
 | 
			
		||||
                            minWidth: column.minWidth
 | 
			
		||||
                              ? column.minWidth
 | 
			
		||||
                              : '47px',
 | 
			
		||||
                            whiteSpace: column.ellipsisTooltip
 | 
			
		||||
                              ? 'nowrap'
 | 
			
		||||
                              : 'normal',
 | 
			
		||||
                          }"
 | 
			
		||||
                        >
 | 
			
		||||
                          <lay-tooltip
 | 
			
		||||
                            v-if="column.ellipsisTooltip"
 | 
			
		||||
                            :content="data[column.key]"
 | 
			
		||||
                            :isAutoShow="true"
 | 
			
		||||
                          >
 | 
			
		||||
                            <slot :name="column.customSlot" :data="data"></slot>
 | 
			
		||||
                          </lay-tooltip>
 | 
			
		||||
                          <slot
 | 
			
		||||
                            v-else
 | 
			
		||||
                            :name="column.customSlot"
 | 
			
		||||
                            :data="data"
 | 
			
		||||
                          ></slot>
 | 
			
		||||
                        </td>
 | 
			
		||||
                      </template>
 | 
			
		||||
                      <!-- 匹 配 Column -->
 | 
			
		||||
                      <template v-else>
 | 
			
		||||
                        <template v-if="column.key in data">
 | 
			
		||||
                          <td
 | 
			
		||||
                            class="layui-table-cell"
 | 
			
		||||
                            :style="{
 | 
			
		||||
                              textAlign: column.align,
 | 
			
		||||
                              width: column.width ? column.width : '0',
 | 
			
		||||
                              minWidth: column.minWidth
 | 
			
		||||
                                ? column.minWidth
 | 
			
		||||
                                : '47px',
 | 
			
		||||
                              whiteSpace: column.ellipsisTooltip
 | 
			
		||||
                                ? 'nowrap'
 | 
			
		||||
                                : 'normal',
 | 
			
		||||
                            }"
 | 
			
		||||
                          >
 | 
			
		||||
                            <lay-tooltip
 | 
			
		||||
                              v-if="column.ellipsisTooltip"
 | 
			
		||||
                              :content="data[column.key]"
 | 
			
		||||
                              :isAutoShow="true"
 | 
			
		||||
                            >
 | 
			
		||||
                              {{ data[column.key] }}
 | 
			
		||||
                            </lay-tooltip>
 | 
			
		||||
                            <span v-else> {{ data[column.key] }} </span>
 | 
			
		||||
                          </td>
 | 
			
		||||
                        </template>
 | 
			
		||||
                      </template>
 | 
			
		||||
                    </template>
 | 
			
		||||
                  <template v-for="name in slotsData" #[name]>
 | 
			
		||||
                    <slot :name="name" :data="data"></slot>
 | 
			
		||||
                  </template>
 | 
			
		||||
                </tr>
 | 
			
		||||
                  <template v-if="slot.expand" #expand>
 | 
			
		||||
                    <slot name="expand" :data="data"></slot>
 | 
			
		||||
                  </template>
 | 
			
		||||
                </table-row>
 | 
			
		||||
              </template>
 | 
			
		||||
            </tbody>
 | 
			
		||||
          </table>
 | 
			
		||||
@ -410,8 +351,12 @@ onMounted(() => {
 | 
			
		||||
          show-skip
 | 
			
		||||
          @jump="change"
 | 
			
		||||
        >
 | 
			
		||||
          <template #prev><lay-icon type="layui-icon-left" /></template>
 | 
			
		||||
          <template #next><lay-icon type="layui-icon-right" /></template>
 | 
			
		||||
          <template #prev>
 | 
			
		||||
            <lay-icon type="layui-icon-left" />
 | 
			
		||||
          </template>
 | 
			
		||||
          <template #next>
 | 
			
		||||
            <lay-icon type="layui-icon-right" />
 | 
			
		||||
          </template>
 | 
			
		||||
        </lay-page>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,7 @@ export default {
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { StringOrNumber } from "./tree.type";
 | 
			
		||||
import { StringOrNumber, CustomKey, CustomString } from "./tree.type";
 | 
			
		||||
import { LayIcon } from "@layui/icons-vue";
 | 
			
		||||
import LayCheckbox from "../checkbox/index.vue";
 | 
			
		||||
import { Ref, useSlots } from "vue";
 | 
			
		||||
@ -13,10 +13,7 @@ import { Tree } from "./tree";
 | 
			
		||||
import { Nullable } from "../../types";
 | 
			
		||||
import LayTransition from "../transition/index.vue";
 | 
			
		||||
 | 
			
		||||
type CustomKey = string | number;
 | 
			
		||||
type CustomString = (() => string) | string;
 | 
			
		||||
 | 
			
		||||
interface TreeData {
 | 
			
		||||
export interface TreeData {
 | 
			
		||||
  id: CustomKey;
 | 
			
		||||
  title: CustomString;
 | 
			
		||||
  children: TreeData[];
 | 
			
		||||
@ -29,7 +26,7 @@ interface TreeData {
 | 
			
		||||
  parentNode: Nullable<TreeData>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface TreeNodeProps {
 | 
			
		||||
export interface TreeNodeProps {
 | 
			
		||||
  tree: Tree;
 | 
			
		||||
  nodeList: TreeData[];
 | 
			
		||||
  showCheckbox: boolean;
 | 
			
		||||
@ -113,9 +110,9 @@ function handleTitleClick(node: TreeData) {
 | 
			
		||||
            { 'layui-tree-iconClick': true },
 | 
			
		||||
          ]"
 | 
			
		||||
        >
 | 
			
		||||
          <LayIcon :type="nodeIconType(node)" @click="handleIconClick(node)" />
 | 
			
		||||
          <lay-icon :type="nodeIconType(node)" @click="handleIconClick(node)" />
 | 
			
		||||
        </span>
 | 
			
		||||
        <LayCheckbox
 | 
			
		||||
        <lay-checkbox
 | 
			
		||||
          v-if="showCheckbox"
 | 
			
		||||
          :modelValue="node.isChecked.value"
 | 
			
		||||
          :disabled="node.isDisabled.value"
 | 
			
		||||
@ -138,13 +135,13 @@ function handleTitleClick(node: TreeData) {
 | 
			
		||||
        </span>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <LayTransition :enable="collapseTransition">
 | 
			
		||||
    <lay-transition :enable="collapseTransition">
 | 
			
		||||
      <div
 | 
			
		||||
        v-if="node.isLeaf.value"
 | 
			
		||||
        class="layui-tree-pack layui-tree-showLine"
 | 
			
		||||
        style="display: block"
 | 
			
		||||
      >
 | 
			
		||||
        <TreeNode
 | 
			
		||||
        <tree-node 
 | 
			
		||||
          :node-list="node.children"
 | 
			
		||||
          :show-checkbox="showCheckbox"
 | 
			
		||||
          :show-line="showLine"
 | 
			
		||||
@ -154,8 +151,6 @@ function handleTitleClick(node: TreeData) {
 | 
			
		||||
          @node-click="recursiveNodeClick"
 | 
			
		||||
        />
 | 
			
		||||
      </div>
 | 
			
		||||
    </LayTransition>
 | 
			
		||||
    </lay-transition>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped></style>
 | 
			
		||||
</template>
 | 
			
		||||
@ -32,3 +32,6 @@ export interface TreeEmits {
 | 
			
		||||
  (e: "update:expandKeys", keys: KeysType): void;
 | 
			
		||||
  (e: "node-click", node: OriginalTreeData, event: Event): void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type CustomKey = string | number;
 | 
			
		||||
export type CustomString = (() => string) | string;
 | 
			
		||||
 | 
			
		||||
@ -237,6 +237,11 @@ export default {
 | 
			
		||||
      <lay-button size="xs">修改</lay-button>
 | 
			
		||||
      <lay-button size="xs" type="primary">删除</lay-button>
 | 
			
		||||
    </template>
 | 
			
		||||
    <template v-slot:expand="{ data }"> 
 | 
			
		||||
      <div style="height:100px;">
 | 
			
		||||
        内容
 | 
			
		||||
      </div>
 | 
			
		||||
    </template>
 | 
			
		||||
  </lay-table>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@ -318,6 +323,103 @@ export default {
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: title 开启子表
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: demo 当表格内容较多不能一次性完全展示时。
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <lay-table :columns="columns6" :dataSource="dataSource6">
 | 
			
		||||
      <template v-slot:expand="{ data }"> 
 | 
			
		||||
        {{ data }} 
 | 
			
		||||
      </template>
 | 
			
		||||
  </lay-table>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { ref } from 'vue'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  setup() {
 | 
			
		||||
 | 
			
		||||
    const columns6 = [
 | 
			
		||||
      {
 | 
			
		||||
        title:"姓名",
 | 
			
		||||
        width:"200px",
 | 
			
		||||
        key:"name"
 | 
			
		||||
      },{
 | 
			
		||||
        title:"成绩",
 | 
			
		||||
        width: "180px",
 | 
			
		||||
        key:"score"
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    const dataSource6 = [
 | 
			
		||||
      {name:"张三", score:100},
 | 
			
		||||
      {name:"李四", score:80},
 | 
			
		||||
      {name:"王二", score:99},
 | 
			
		||||
      {name:"麻子", score:92},
 | 
			
		||||
      {name:"无名", score:60},
 | 
			
		||||
      {name:"有名", score:70},
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      columns6,
 | 
			
		||||
      dataSource6
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: title 树形表格
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: demo 树形数据的展示,当数据中有 children 字段时会自动展示为树形表格
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <lay-table :columns="columns7" :dataSource="dataSource7">
 | 
			
		||||
  </lay-table>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { ref } from 'vue'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  setup() {
 | 
			
		||||
 | 
			
		||||
    const columns7 = [
 | 
			
		||||
      {
 | 
			
		||||
        title:"姓名",
 | 
			
		||||
        width:"200px",
 | 
			
		||||
        key:"name"
 | 
			
		||||
      },{
 | 
			
		||||
        title:"成绩",
 | 
			
		||||
        width: "180px",
 | 
			
		||||
        key:"score"
 | 
			
		||||
      },
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    const dataSource7 = [
 | 
			
		||||
      {name:"张三", score:100, children: [{name:"张三", score:100},{name:"张三", score:100}]},
 | 
			
		||||
      {name:"李四", score:80, children: [{name:"张三", score:100},{name:"张三", score:100}]},
 | 
			
		||||
      {name:"王二", score:99, children: [{name:"张三", score:100},{name:"张三", score:100}]},
 | 
			
		||||
      {name:"麻子", score:92, children: [{name:"张三", score:100},{name:"张三", score:100}]},
 | 
			
		||||
      {name:"无名", score:60, children: [{name:"张三", score:100},{name:"张三", score:100}]},
 | 
			
		||||
      {name:"有名", score:70, children: [{name:"张三", score:100},{name:"张三", score:100}]},
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      columns7,
 | 
			
		||||
      dataSource7
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
::: title Table 属性
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user