Skip to content

Commit

Permalink
[Table] 树形结构新特性:展开/收起全部,拖拽排序等 (#879)
Browse files Browse the repository at this point in the history
* docs(notification): 插件调用与函数式调用

* fix(table): merged cells border style

* feat(table): support expand all and fold all

* feat(table): update API

* feat(table): support defaultExpandAll

* refactor(table): expandAll and foldAll

* fix(table): 展开或收起全部

* feat(table): tree drag sort

* feat(table): drag sort

* feat(table): update documents

* feat(table): drag sort + expand all + fold all

* fix(table): tree, rowIndex

* refactor(table): 统一树形结构赋值方式

Co-authored-by: sheepluo <[email protected]>
  • Loading branch information
chaishi and sheepluo authored May 16, 2022
1 parent cc4bbe5 commit 1c6bba4
Show file tree
Hide file tree
Showing 12 changed files with 851 additions and 272 deletions.
2 changes: 1 addition & 1 deletion examples/dialog/demos/attach.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export default Vue.extend({
},
});
</script>
<style>
<style scoped>
.t-button {
margin-right: 20px;
}
Expand Down
122 changes: 98 additions & 24 deletions examples/table/demos/tree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
<div>
<div>
<t-button theme="default" @click="setData1">重置数据</t-button>
<t-button theme="default" style="margin-left: 16px" @click="onRowToggle">展开/收起可见行</t-button>
<t-button theme="default" style="margin-left: 16px" @click="onRowToggle">任意节点展开/收起</t-button>
<t-button theme="default" style="margin-left: 16px" @click="onExpandAllToggle">{{
expandAll ? '收起全部' : '展开全部'
}}</t-button>
<t-checkbox v-model="customTreeExpandAndFoldIcon" style="margin-left: 16px; vertical-align: middle">
自定义折叠/展开图标
</t-checkbox>
Expand All @@ -11,15 +14,20 @@
<!-- 第一列展开树结点,缩进为 24px,子节点字段 childrenKey 默认为 children -->
<!-- !!! 树形结构 EnhancedTable 才支持,普通 Table 不支持 !!! -->
<!-- treeNodeColumnIndex 定义第几列作为树结点展开列,默认为第一列 -->
<!-- tree.defaultExpandAll: true 默认展开全部 -->
<!-- this.$refs.table.dataSource 查看树形结构平铺数据 -->
<t-enhanced-table
ref="table"
rowKey="key"
drag-sort="row-handler"
:data="data"
:columns="columns"
:tree="{ childrenKey: 'list', treeNodeColumnIndex: 1 }"
:tree="{ childrenKey: 'list', treeNodeColumnIndex: 2 }"
:tree-expand-and-fold-icon="customTreeExpandAndFoldIcon ? treeExpandAndFoldIconRender : undefined"
:pagination="pagination"
:beforeDragSort="beforeDragSort"
@page-change="onPageChange"
@abnormal-drag-sort="onAbnormalDragSort"
></t-enhanced-table>

<!-- 第二列展开树结点,缩进为 12px,示例代码有效,勿删 -->
Expand All @@ -31,22 +39,24 @@
:pagination="defaultPagination"
:data="data"
:columns="columns"
:tree="{ indent: 12, childrenKey: 'list' }"
:tree="{ indent: 12, childrenKey: 'list', defaultExpandAll: true }"
@page-change="onPageChange"
></t-enhanced-table> -->
</div>
</template>
<script lang="jsx">
import { EnhancedTable } from 'tdesign-vue';
import { ChevronRightIcon, ChevronDownIcon } from 'tdesign-icons-vue';
import { ChevronRightIcon, ChevronDownIcon, MoveIcon } from 'tdesign-icons-vue';
const TOTAL = 5;
function getData(currentPage = 1) {
const data = [];
const pageInfo = `${currentPage}`;
for (let i = 0; i < 5; i++) {
// const pageInfo = `第 ${currentPage} 页`;
for (let i = 0; i < TOTAL; i++) {
const obj = {
id: i,
key: `我是 ${i}_${currentPage}${pageInfo}`,
key: `我是 ${i}_${currentPage}`,
platform: i % 2 === 0 ? '共有' : '私有',
type: ['String', 'Number', 'Array', 'Object'][i % 4],
default: ['-', '0', '[]', '{}'][i % 4],
Expand All @@ -64,14 +74,14 @@ function getData(currentPage = 1) {
const secondObj = {
...obj,
id: secondIndex,
key: `我是 ${secondIndex}_${currentPage}${pageInfo}`,
key: `我是 ${secondIndex}_${currentPage}`,
};
secondObj.list = new Array(3).fill(null).map((m, n) => {
const thirdIndex = secondIndex * 1000 + 100 * m + (n + 1) * 10;
return {
...obj,
id: thirdIndex,
key: `我是 ${thirdIndex}_${currentPage}${pageInfo}`,
key: `我是 ${thirdIndex}_${currentPage}`,
};
});
return secondObj;
Expand All @@ -89,39 +99,53 @@ export default {
return {
customTreeExpandAndFoldIcon: false,
data,
expandAll: false,
pagination: {
current: 1,
pageSize: 10,
total: 100,
total: TOTAL,
},
defaultPagination: {
defaultCurrent: 1,
defaultPageSize: 10,
total: 100,
total: TOTAL,
},
columns: [
{
// 列拖拽排序必要参数
colKey: 'drag',
title: '排序',
// eslint-disable-next-line @typescript-eslint/no-unused-vars
cell: (h) => <MoveIcon />,
width: 80,
},
{
colKey: 'id',
title: '编号',
ellipsis: true,
width: 100,
},
{
width: 220,
width: 180,
colKey: 'key',
title: '名称',
ellipsis: true,
},
{
colKey: 'platform',
title: '平台',
},
{
colKey: 'type',
title: '类型',
width: 80,
cell: (h, { row }) => row.platform === 'New' ? (
<t-tag size="small" theme="primary">
{row.platform}
</t-tag>
) : (
row.platform
),
},
{
colKey: 'operate',
width: 280,
width: 340,
title: '操作',
align: 'center',
// 增、删、改、查 等操作
Expand All @@ -131,6 +155,12 @@ export default {
<t-button variant="text" onClick={() => this.appendTo(row)}>
插入
</t-button>
<t-button variant="text" onClick={() => this.insertBefore(row)}>
前插
</t-button>
<t-button variant="text" onClick={() => this.insertAfter(row)}>
后插
</t-button>
<t-button variant="text" onClick={() => this.onEditClick(row)}>
更新
</t-button>
Expand All @@ -147,6 +177,11 @@ export default {
};
},
// 默认展开全部。示例代码有效,勿删
// mounted() {
// this.$refs.table.expandAll();
// },
methods: {
// 全新赋值
setData1() {
Expand Down Expand Up @@ -179,7 +214,7 @@ export default {
console.log(`${message}`, allRowData);
},
// 新增
// 新增子节点
appendTo(row) {
const randomKey = Math.round(Math.random() * Math.random() * 1000) + 10000;
this.$refs.table.appendTo(row.key, {
Expand All @@ -191,19 +226,38 @@ export default {
this.$message.success(`已插入子节点我是 ${randomKey} 号,请展开查看`);
},
// 当前节点之前,新增兄弟节前
insertBefore(row) {
const randomKey = Math.round(Math.random() * Math.random() * 1000) + 10000;
this.$refs.table.insertBefore(row.key, {
id: randomKey,
key: `我是 ${randomKey}`,
platform: '私有',
type: 'Number',
});
this.$message.success(`已插入子节点我是 ${randomKey} 号,请展开查看`);
},
// 当前节点之后,新增兄弟节前
insertAfter(row) {
const randomKey = Math.round(Math.random() * Math.random() * 1000) + 10000;
this.$refs.table.insertAfter(row.key, {
id: randomKey,
key: `我是 ${randomKey}`,
platform: '私有',
type: 'Number',
});
this.$message.success(`已插入子节点我是 ${randomKey} 号,请展开查看`);
},
onPageChange(pageInfo) {
this.pagination.current = pageInfo.current;
this.pagination.pageSize = pageInfo.pageSize;
this.data = getData(pageInfo.current);
},
onRowToggle() {
const rowIds = [
'我是 1_1 号(第 1 页)',
'我是 2_1 号(第 1 页)',
'我是 3_1 号(第 1 页)',
'我是 4_1 号(第 1 页)',
];
const rowIds = ['我是 1_1 号', '我是 2_1 号', '我是 3_1 号', '我是 4_1 号'];
rowIds.forEach((id) => {
// getData 参数为行唯一标识,lodash.get(row, rowKey)
const rowData = this.$refs.table.getData(id);
Expand All @@ -217,6 +271,26 @@ export default {
treeExpandAndFoldIconRender(h, { type }) {
return type === 'expand' ? <ChevronRightIcon /> : <ChevronDownIcon />;
},
onExpandAllToggle() {
this.expandAll = !this.expandAll;
this.expandAll ? this.$refs.table.expandAll() : this.$refs.table.foldAll();
},
onAbnormalDragSort(params) {
console.log(params);
// this.$message.warning(params.reason);
if (params.code === 1001) {
this.$message.warning('不同层级的元素,不允许调整顺序');
}
},
// 应用于需要阻止拖拽排序的场景。如:当子节点存在时,则不允许调整顺序
// 返回值为 true,允许拖拽排序;返回值 为 false,则阻止拖拽排序
beforeDragSort(params) {
console.log(params);
return true;
},
},
};
</script>
Expand Down
22 changes: 19 additions & 3 deletions examples/table/table.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ maxHeight | String / Number | - | 表格最大高度,超出后会出现滚动
pagination | Object | - | 分页配置,值为空则不显示。具体 API 参考分页组件。当 `data` 数据长度超过分页大小时,会自动对本地数据 `data` 进行排序,如果不希望对于 `data` 进行排序,可以设置 `disableDataPage = true`。TS 类型:`PaginationProps`[Pagination API Documents](./pagination?tab=api)[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/table/type.ts) | N
rowAttributes | Object / Array / Function | - | HTML 标签 `tr` 的属性。类型为 Function 时,参数说明:`params.row` 表示行数据;`params.rowIndex` 表示行下标;`params.type=body` 表示属性作用于 `tbody` 中的元素;`params.type=foot` 表示属性作用于 `tfoot` 中的元素。<br />示例一:{ draggable: true },<br />示例二:[{ draggable: true }, { title: '超出省略显示' }]。<br /> 示例三:() => [{ draggable: true }]。TS 类型:`TableRowAttributes<T>` `type TableRowAttributes<T> = HTMLElementAttributes | ((params: { row: T; rowIndex: number; type: 'body' | 'foot' }) => HTMLElementAttributes) | Array<TableRowAttributes<T>>`[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/table/type.ts) | N
rowClassName | String / Object / Array / Function | - | 行类名,泛型 T 指表格数据类型。`params.row` 表示行数据;`params.rowIndex` 表示行下标;`params.type=body` 表示类名作用于 `tbody` 中的元素;`params.type=body` 表示类名作用于 `tfoot` 中的元素。TS 类型:`ClassName | ((params: RowClassNameParams<T>) => ClassName)` `interface RowClassNameParams<T> { row: T; rowIndex: number; type?: 'body' | 'foot' }`[通用类型定义](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts)[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/table/type.ts) | N
rowKey | String | - | 必需。使用 rowKey 唯一标识一行数据 | Y
rowKey | String | 'id' | 必需。使用 rowKey 唯一标识一行数据 | Y
rowspanAndColspan | Function | - | 用于自定义合并单元格,泛型 T 指表格数据类型。示例:`({ row, col, rowIndex, colIndex }) => { rowspan: 2, colspan: 3 }`。TS 类型:`TableRowspanAndColspanFunc<T>` `type TableRowspanAndColspanFunc<T> = (params: BaseTableCellParams<T>) => RowspanColspan` `interface RowspanColspan { colspan?: number; rowspan?: number }`[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/table/type.ts) | N
scroll | Object | - | 懒加载和虚拟滚动。为保证组件收益最大化,当数据量小于阈值 `scroll.threshold` 时,无论虚拟滚动的配置是否存在,组件内部都不会开启虚拟滚动,`scroll.threshold` 默认为 `100`。TS 类型:`TableScroll` | N
size | String | medium | 表格尺寸。可选项:small/medium/large。TS 类型:`SizeEnum`[通用类型定义](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
Expand Down Expand Up @@ -167,21 +167,26 @@ type | String | single | `colKey` 值为 `row-select` 时表示行选中列,

名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
tree | Object | - | 树形结构相关配置。`tree.indent` 表示树结点缩进距离,单位:px,默认为 24px。`tree.treeNodeColumnIndex` 表示树结点在第几列渲染,默认为 0 ,第一列。`tree.childrenKey` 表示树形结构子节点字段,默认为 children。`tree.checkStrictly` 表示树形结构的行选中(多选),父子行选中是否独立,默认独立,值为 true。TS 类型:`TableTreeConfig` `interface TableTreeConfig { indent?: number; treeNodeColumnIndex?: number; childrenKey?: 'children'; checkStrictly?: boolean }`[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/table/type.ts) | N
beforeDragSort | Function | - | 树形结构中,拖拽排序前控制,返回值为 `true` 则继续排序;返回值为 `false` 则中止排序还原数据。TS 类型:`(context: DragSortContext<T>) => boolean` | N
tree | Object | - | 树形结构相关配置。具体属性文档查看 `TableTreeConfig` 相关描述。TS 类型:`TableTreeConfig` | N
treeExpandAndFoldIcon | Function | - | 自定义树形结构展开图标,支持全局配置 `GlobalConfigProvider`。TS 类型:`TNode<{ type: 'expand' | 'fold' }>`[通用类型定义](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
`PrimaryTableProps<T>` | \- | - | 继承 `PrimaryTableProps<T>` 中的全部 API | N
onAbnormalDragSort | Function | | TS 类型:`(context: TableAbnormalDragSortContext<T>) => void`<br/>异常拖拽排序时触发,如:树形结构中,非同层级之间的交换。`context.code` 指交换异常错误码,固定值;`context.reason` 指交换异常的原因。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/table/type.ts)。<br/>`interface TableAbnormalDragSortContext<T> { code: number; reason: string }`<br/> | N
onTreeExpandChange | Function | | TS 类型:`(context: TableTreeExpandChangeContext<T>) => void`<br/>树形结构,用户操作引起节点展开或收起时触发,代码操作不会触发。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/table/type.ts)。<br/>`interface TableTreeExpandChangeContext<T> { row: T; rowIndex: number; rowState: TableRowState<T> }`<br/> | N

### EnhancedTable Events

名称 | 参数 | 描述
-- | -- | --
abnormal-drag-sort | `(context: TableAbnormalDragSortContext<T>)` | 异常拖拽排序时触发,如:树形结构中,非同层级之间的交换。`context.code` 指交换异常错误码,固定值;`context.reason` 指交换异常的原因。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/table/type.ts)。<br/>`interface TableAbnormalDragSortContext<T> { code: number; reason: string }`<br/>
tree-expand-change | `(context: TableTreeExpandChangeContext<T>)` | 树形结构,用户操作引起节点展开或收起时触发,代码操作不会触发。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/table/type.ts)。<br/>`interface TableTreeExpandChangeContext<T> { row: T; rowIndex: number; rowState: TableRowState<T> }`<br/>

### EnhancedTableInstanceFunctions 组件实例方法

名称 | 参数 | 返回值 | 描述
-- | -- | -- | --
expandAll | \- | \- | 必需。展开全部行
foldAll | \- | \- | 必需。折叠全部行
getData | `(key: TableRowValue)` | `TableRowState<T>` | 必需。树形结构中,用于获取行数据所有信息。泛型 `T` 表示行数据类型。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/table/type.ts)。<br/>`type TableRowValue = string | number`<br/>
remove | `(key: TableRowValue)` | \- | 必需。树形结构中,移除指定节点
setData | `(key: TableRowValue, newRowData: T)` | \- | 必需。树形结构中,用于更新行数据。泛型 `T` 表示行数据类型
Expand All @@ -194,11 +199,12 @@ toggleExpandData | `(p: { row: T, rowIndex: number})` | \- | 必需。展开或
disabled | Boolean | false | 表格行是否禁用选中 | N
expandChildrenLength | Number | - | 当前节点展开的子节点数量 | N
expanded | Boolean | false | 必需。表格行是否展开 | Y
id | String / Number | - | 必需。唯一标识 | Y
level | Number | - | 当前节点层级。TS 类型:`number` | N
parent | \- | - | 父节点。TS 类型:`TableRowState<T>` | N
path | Array | - | 当前节点路径。TS 类型:`TableRowState<T>[]` | N
row | \- | - | 必需。原始表格行数据。TS 类型:`T` | Y
rowIndex | Number | - | 必需。表格行下标 | Y
rowIndex | Number | - | 必需。表格行下标,值为 `-1` 标识当前行未展开显示 | Y

### TableColumnFilter

Expand Down Expand Up @@ -232,3 +238,13 @@ displayType | String | auto-width | 指列配置弹框中,各列的字段平
fields | Array | - | 用于设置允许用户对哪些列进行显示或隐藏的控制,默认为全部字段。TS 类型:`string[]` | N
hideTriggerButton | Boolean | false | 是否隐藏表格组件内置的“列配置”按钮 | N
placement | String | top-right | 列配置按钮基于表格的放置位置:左上角、右上角、左下角、右下角等。可选项:top-left/top-right/bottom-left/bottom-right | N

### TableTreeConfig

名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
checkStrictly | Boolean | true | 表示树形结构的行选中(多选),父子行选中是否独立 | N
childrenKey | String | children | 树形结构子节点字段,示例:`childrenKey='list'`。一般应用在数据 `data` 的子节点字段不是 `children` 的场景 | N
defaultExpandAll | Boolean | false | 是否默认展开全部,仅默认情况有效。如果希望自由控制树形结构的展开或收起,可使用实例方法 `expandAll``foldAll` | N
indent | Number | 24 | 树结点缩进距离,单位:px | N
treeNodeColumnIndex | Number | 0 | 树结点在第几列渲染,默认为第一列 | N
2 changes: 1 addition & 1 deletion src/table/base-table-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export default {
/** 使用 rowKey 唯一标识一行数据 */
rowKey: {
type: String,
default: '',
default: 'id',
required: true,
},
/** 用于自定义合并单元格,泛型 T 指表格数据类型。示例:`({ row, col, rowIndex, colIndex }) => { rowspan: 2, colspan: 3 }` */
Expand Down
8 changes: 7 additions & 1 deletion src/table/enhanced-table-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,20 @@ import { TdEnhancedTableProps } from '../table/type';
import { PropType } from 'vue';

export default {
/** 树形结构相关配置。`tree.indent` 表示树结点缩进距离,单位:px,默认为 24px。`tree.treeNodeColumnIndex` 表示树结点在第几列渲染,默认为 0 ,第一列。`tree.childrenKey` 表示树形结构子节点字段,默认为 children。`tree.checkStrictly` 表示树形结构的行选中(多选),父子行选中是否独立,默认独立,值为 true */
/** 树形结构中,拖拽排序前控制,返回值为 `true` 则继续排序;返回值为 `false` 则中止排序还原数据 */
beforeDragSort: {
type: Function as PropType<TdEnhancedTableProps['beforeDragSort']>,
},
/** 树形结构相关配置。具体属性文档查看 `TableTreeConfig` 相关描述 */
tree: {
type: Object as PropType<TdEnhancedTableProps['tree']>,
},
/** 自定义树形结构展开图标,支持全局配置 `GlobalConfigProvider` */
treeExpandAndFoldIcon: {
type: Function as PropType<TdEnhancedTableProps['treeExpandAndFoldIcon']>,
},
/** 异常拖拽排序时触发,如:树形结构中,非同层级之间的交换。`context.code` 指交换异常错误码,固定值;`context.reason` 指交换异常的原因 */
onAbnormalDragSort: Function as PropType<TdEnhancedTableProps['onAbnormalDragSort']>,
/** 树形结构,用户操作引起节点展开或收起时触发,代码操作不会触发 */
onTreeExpandChange: Function as PropType<TdEnhancedTableProps['onTreeExpandChange']>,
};
Loading

0 comments on commit 1c6bba4

Please sign in to comment.