✨(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;
|
table-layout: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layui-table tr {
|
|
||||||
// display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-table th {
|
.layui-table th {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
@ -112,7 +108,7 @@
|
|||||||
.layui-table-view .layui-table {
|
.layui-table-view .layui-table {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border-collapse: separate;
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layui-table-view .layui-table[lay-skin="line"] {
|
.layui-table-view .layui-table[lay-skin="line"] {
|
||||||
@ -240,8 +236,8 @@
|
|||||||
.layui-table-tool-panel li {
|
.layui-table-tool-panel li {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
// white-space: nowrap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.layui-table-call-ellipsis{
|
.layui-table-call-ellipsis{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -360,6 +356,12 @@
|
|||||||
-webkit-box-pack: center;
|
-webkit-box-pack: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.layui-table-cell-expand-icon {
|
||||||
|
border: 1px solid #eee;
|
||||||
|
margin-right: 8px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
.layui-table-body {
|
.layui-table-body {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
@ -370,7 +372,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
&::-webkit-scrollbar-thumb {
|
||||||
background-color: rgba(0, 0, 0, 0.4);
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
border: 3px solid transparent;
|
border: 3px solid transparent;
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
@ -635,3 +637,7 @@ body .layui-table-tips .layui-layer-content {
|
|||||||
.layui-table-view {
|
.layui-table-view {
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.layui-table-cell-expand{
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
}
|
@ -6,7 +6,7 @@ export default {
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import "./index.less";
|
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 { v4 as uuidv4 } from "../../utils/guidUtil";
|
||||||
import { Recordable } from "../../types";
|
import { Recordable } from "../../types";
|
||||||
import LayCheckbox from "../checkbox/index.vue";
|
import LayCheckbox from "../checkbox/index.vue";
|
||||||
@ -14,6 +14,7 @@ import LayDropdown from "../dropdown/index.vue";
|
|||||||
import LayTooltip from "../tooltip/index.vue";
|
import LayTooltip from "../tooltip/index.vue";
|
||||||
import { LayIcon } from "@layui/icons-vue";
|
import { LayIcon } from "@layui/icons-vue";
|
||||||
import LayPage from "../page/index.vue";
|
import LayPage from "../page/index.vue";
|
||||||
|
import TableRow from "./TableRow.vue";
|
||||||
|
|
||||||
export interface LayTableProps {
|
export interface LayTableProps {
|
||||||
id?: string;
|
id?: string;
|
||||||
@ -49,7 +50,7 @@ const slots = slot.default && slot.default();
|
|||||||
|
|
||||||
const allChecked = ref(false);
|
const allChecked = ref(false);
|
||||||
const tableDataSource = ref([...props.dataSource]);
|
const tableDataSource = ref([...props.dataSource]);
|
||||||
const tableSelectedKeys = ref([...props.selectedKeys]);
|
const tableSelectedKeys = ref<Recordable[]>([...props.selectedKeys]);
|
||||||
const tableColumns = ref([...props.columns]);
|
const tableColumns = ref([...props.columns]);
|
||||||
const tableColumnKeys = ref(
|
const tableColumnKeys = ref(
|
||||||
props.columns.map((item: any) => {
|
props.columns.map((item: any) => {
|
||||||
@ -81,7 +82,7 @@ const changeAll = function (checked: any) {
|
|||||||
|
|
||||||
watch(
|
watch(
|
||||||
tableSelectedKeys,
|
tableSelectedKeys,
|
||||||
function () {
|
() => {
|
||||||
if (tableSelectedKeys.value.length === props.dataSource.length) {
|
if (tableSelectedKeys.value.length === props.dataSource.length) {
|
||||||
allChecked.value = true;
|
allChecked.value = true;
|
||||||
} else {
|
} else {
|
||||||
@ -108,7 +109,6 @@ const contextmenu = function (data: any, evt: MouseEvent) {
|
|||||||
emit("contextmenu", data, evt);
|
emit("contextmenu", data, evt);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 打印 table 数据
|
|
||||||
const print = function () {
|
const print = function () {
|
||||||
let subOutputRankPrint = document.getElementById(tableId) as HTMLElement;
|
let subOutputRankPrint = document.getElementById(tableId) as HTMLElement;
|
||||||
let newContent = subOutputRankPrint.innerHTML;
|
let newContent = subOutputRankPrint.innerHTML;
|
||||||
@ -163,16 +163,12 @@ function exportToExcel(headerList: any, bodyList: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const sortTable = (e: any, key: string, sort: string) => {
|
const sortTable = (e: any, key: string, sort: string) => {
|
||||||
// 当前排序
|
|
||||||
let currentSort = e.target.parentNode.getAttribute("lay-sort");
|
let currentSort = e.target.parentNode.getAttribute("lay-sort");
|
||||||
// 点击排序
|
|
||||||
if (sort === "desc") {
|
if (sort === "desc") {
|
||||||
if (currentSort === sort) {
|
if (currentSort === sort) {
|
||||||
// 取消排序
|
|
||||||
e.target.parentNode.setAttribute("lay-sort", "");
|
e.target.parentNode.setAttribute("lay-sort", "");
|
||||||
tableDataSource.value = [...props.dataSource];
|
tableDataSource.value = [...props.dataSource];
|
||||||
} else {
|
} else {
|
||||||
// 进行 desc 排序
|
|
||||||
e.target.parentNode.setAttribute("lay-sort", "desc");
|
e.target.parentNode.setAttribute("lay-sort", "desc");
|
||||||
tableDataSource.value.sort((x, y) => {
|
tableDataSource.value.sort((x, y) => {
|
||||||
if (x[key] < y[key]) return 1;
|
if (x[key] < y[key]) return 1;
|
||||||
@ -182,11 +178,9 @@ const sortTable = (e: any, key: string, sort: string) => {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (currentSort === sort) {
|
if (currentSort === sort) {
|
||||||
// 取消排序
|
|
||||||
e.target.parentNode.setAttribute("lay-sort", "");
|
e.target.parentNode.setAttribute("lay-sort", "");
|
||||||
tableDataSource.value = [...props.dataSource];
|
tableDataSource.value = [...props.dataSource];
|
||||||
} else {
|
} else {
|
||||||
// 进行 asc 排序
|
|
||||||
e.target.parentNode.setAttribute("lay-sort", "asc");
|
e.target.parentNode.setAttribute("lay-sort", "asc");
|
||||||
tableDataSource.value.sort((x, y) => {
|
tableDataSource.value.sort((x, y) => {
|
||||||
if (x[key] < y[key]) return -1;
|
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 tableHeader = ref<HTMLElement | null>(null);
|
||||||
let tableBody = ref<HTMLElement | null>(null);
|
let tableBody = ref<HTMLElement | null>(null);
|
||||||
|
|
||||||
// 拖动监听
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
tableBody.value?.addEventListener("scroll", () => {
|
tableBody.value?.addEventListener("scroll", () => {
|
||||||
tableHeader.value!.scrollLeft = tableBody.value?.scrollLeft || 0;
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -315,86 +316,26 @@ onMounted(() => {
|
|||||||
<div class="layui-table-body layui-table-main" ref="tableBody">
|
<div class="layui-table-body layui-table-main" ref="tableBody">
|
||||||
<table class="layui-table" :lay-size="size">
|
<table class="layui-table" :lay-size="size">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
<!-- 渲染 -->
|
||||||
<template v-for="data in tableDataSource" :key="data">
|
<template v-for="data in tableDataSource" :key="data">
|
||||||
<tr
|
<table-row
|
||||||
@click.stop="rowClick(data, $event)"
|
:id="id"
|
||||||
@dblclick.stop="rowDoubleClick(data, $event)"
|
:data="data"
|
||||||
@contextmenu.stop="contextmenu(data, $event)"
|
:columns="columns"
|
||||||
|
:checkbox="checkbox"
|
||||||
|
:tableColumnKeys="tableColumnKeys"
|
||||||
|
@row="rowClick"
|
||||||
|
@row-double="rowDoubleClick"
|
||||||
|
@contextmenu="contextmenu"
|
||||||
|
v-model:selectedKeys="tableSelectedKeys"
|
||||||
>
|
>
|
||||||
<!-- 复选框 -->
|
<template v-for="name in slotsData" #[name]>
|
||||||
<td v-if="checkbox" class="layui-table-col-special">
|
<slot :name="name" :data="data"></slot>
|
||||||
<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>
|
</template>
|
||||||
</tr>
|
<template v-if="slot.expand" #expand>
|
||||||
|
<slot name="expand" :data="data"></slot>
|
||||||
|
</template>
|
||||||
|
</table-row>
|
||||||
</template>
|
</template>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -410,8 +351,12 @@ onMounted(() => {
|
|||||||
show-skip
|
show-skip
|
||||||
@jump="change"
|
@jump="change"
|
||||||
>
|
>
|
||||||
<template #prev><lay-icon type="layui-icon-left" /></template>
|
<template #prev>
|
||||||
<template #next><lay-icon type="layui-icon-right" /></template>
|
<lay-icon type="layui-icon-left" />
|
||||||
|
</template>
|
||||||
|
<template #next>
|
||||||
|
<lay-icon type="layui-icon-right" />
|
||||||
|
</template>
|
||||||
</lay-page>
|
</lay-page>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,7 +5,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { StringOrNumber } from "./tree.type";
|
import { StringOrNumber, CustomKey, CustomString } from "./tree.type";
|
||||||
import { LayIcon } from "@layui/icons-vue";
|
import { LayIcon } from "@layui/icons-vue";
|
||||||
import LayCheckbox from "../checkbox/index.vue";
|
import LayCheckbox from "../checkbox/index.vue";
|
||||||
import { Ref, useSlots } from "vue";
|
import { Ref, useSlots } from "vue";
|
||||||
@ -13,10 +13,7 @@ import { Tree } from "./tree";
|
|||||||
import { Nullable } from "../../types";
|
import { Nullable } from "../../types";
|
||||||
import LayTransition from "../transition/index.vue";
|
import LayTransition from "../transition/index.vue";
|
||||||
|
|
||||||
type CustomKey = string | number;
|
export interface TreeData {
|
||||||
type CustomString = (() => string) | string;
|
|
||||||
|
|
||||||
interface TreeData {
|
|
||||||
id: CustomKey;
|
id: CustomKey;
|
||||||
title: CustomString;
|
title: CustomString;
|
||||||
children: TreeData[];
|
children: TreeData[];
|
||||||
@ -29,7 +26,7 @@ interface TreeData {
|
|||||||
parentNode: Nullable<TreeData>;
|
parentNode: Nullable<TreeData>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TreeNodeProps {
|
export interface TreeNodeProps {
|
||||||
tree: Tree;
|
tree: Tree;
|
||||||
nodeList: TreeData[];
|
nodeList: TreeData[];
|
||||||
showCheckbox: boolean;
|
showCheckbox: boolean;
|
||||||
@ -113,9 +110,9 @@ function handleTitleClick(node: TreeData) {
|
|||||||
{ 'layui-tree-iconClick': true },
|
{ 'layui-tree-iconClick': true },
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<LayIcon :type="nodeIconType(node)" @click="handleIconClick(node)" />
|
<lay-icon :type="nodeIconType(node)" @click="handleIconClick(node)" />
|
||||||
</span>
|
</span>
|
||||||
<LayCheckbox
|
<lay-checkbox
|
||||||
v-if="showCheckbox"
|
v-if="showCheckbox"
|
||||||
:modelValue="node.isChecked.value"
|
:modelValue="node.isChecked.value"
|
||||||
:disabled="node.isDisabled.value"
|
:disabled="node.isDisabled.value"
|
||||||
@ -138,13 +135,13 @@ function handleTitleClick(node: TreeData) {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<LayTransition :enable="collapseTransition">
|
<lay-transition :enable="collapseTransition">
|
||||||
<div
|
<div
|
||||||
v-if="node.isLeaf.value"
|
v-if="node.isLeaf.value"
|
||||||
class="layui-tree-pack layui-tree-showLine"
|
class="layui-tree-pack layui-tree-showLine"
|
||||||
style="display: block"
|
style="display: block"
|
||||||
>
|
>
|
||||||
<TreeNode
|
<tree-node
|
||||||
:node-list="node.children"
|
:node-list="node.children"
|
||||||
:show-checkbox="showCheckbox"
|
:show-checkbox="showCheckbox"
|
||||||
:show-line="showLine"
|
:show-line="showLine"
|
||||||
@ -154,8 +151,6 @@ function handleTitleClick(node: TreeData) {
|
|||||||
@node-click="recursiveNodeClick"
|
@node-click="recursiveNodeClick"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</LayTransition>
|
</lay-transition>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
|
@ -32,3 +32,6 @@ export interface TreeEmits {
|
|||||||
(e: "update:expandKeys", keys: KeysType): void;
|
(e: "update:expandKeys", keys: KeysType): void;
|
||||||
(e: "node-click", node: OriginalTreeData, event: Event): 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">修改</lay-button>
|
||||||
<lay-button size="xs" type="primary">删除</lay-button>
|
<lay-button size="xs" type="primary">删除</lay-button>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-slot:expand="{ data }">
|
||||||
|
<div style="height:100px;">
|
||||||
|
内容
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</lay-table>
|
</lay-table>
|
||||||
</template>
|
</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 属性
|
::: title Table 属性
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user