Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Table] 支持获取获取全部树形结构数据 #931

Merged
merged 20 commits into from
May 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
49072ba
docs(notification): 插件调用与函数式调用
Feb 11, 2022
8e5badf
Merge remote-tracking branch 'upstream/develop' into develop
Feb 14, 2022
5d3dd2a
Merge remote-tracking branch 'upstream/develop' into develop
Feb 15, 2022
df1f39a
Merge remote-tracking branch 'upstream/develop' into develop
chaishi Mar 23, 2022
e9a6f2e
Merge remote-tracking branch 'upstream/develop' into develop
chaishi Mar 28, 2022
993a2a4
Merge remote-tracking branch 'upstream/develop' into develop
chaishi Mar 29, 2022
bbe4c10
fix(table): merged cells border style
chaishi Mar 29, 2022
51a9b4b
feat: merge from upstream/develop
chaishi Mar 31, 2022
93a15e0
Merge remote-tracking branch 'upstream/develop' into develop
chaishi Apr 21, 2022
e57dd2d
Merge remote-tracking branch 'upstream/develop' into develop
chaishi Apr 25, 2022
36d3778
Merge remote-tracking branch 'upstream/develop' into develop
chaishi Apr 30, 2022
1db46ab
Merge remote-tracking branch 'upstream/develop' into develop
chaishi May 10, 2022
edd9e3b
Merge remote-tracking branch 'upstream/develop' into develop
chaishi May 10, 2022
9b4b001
Merge remote-tracking branch 'upstream/develop' into develop
chaishi May 13, 2022
267b4ea
Merge remote-tracking branch 'upstream/develop' into develop
chaishi May 16, 2022
95996fe
Merge remote-tracking branch 'upstream/develop' into develop
chaishi May 21, 2022
871f1b1
fix(table): toggleData and FoldAll
chaishi May 21, 2022
f5bb2e9
fix(table): 树形结构中,动态设置行选中列时,禁用功能失效
chaishi May 21, 2022
ad67e04
feat(table): add getTreeNode; 支持为根节点添加新元素
chaishi May 29, 2022
659b6b5
test: update snapshots
chaishi May 29, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 36 additions & 3 deletions examples/table/demos/tree.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
<template>
<div>
<div>
<t-button theme="default" @click="setData1">重置数据</t-button>
<t-button @click="appendToRoot">添加根节点</t-button>
<t-button theme="default" style="margin-left: 16px" @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="onExpandAllToggle">{{
expandAll ? '收起全部' : '展开全部'
}}</t-button>
<t-checkbox v-model="customTreeExpandAndFoldIcon" style="margin-left: 16px; vertical-align: middle">
<t-button theme="default" style="margin-left: 16px" @click="getTreeNode">获取全部树形结构</t-button>
</div>
<br />
<div>
<t-checkbox v-model="customTreeExpandAndFoldIcon" style="vertical-align: middle">
自定义折叠/展开图标
</t-checkbox>
</div>
Expand All @@ -28,6 +33,7 @@
:beforeDragSort="beforeDragSort"
@page-change="onPageChange"
@abnormal-drag-sort="onAbnormalDragSort"
@drag-sort="onDragSort"
></t-enhanced-table>

<!-- 第二列展开树结点,缩进为 12px,示例代码有效,勿删 -->
Expand Down Expand Up @@ -272,11 +278,33 @@ export default {
return type === 'expand' ? <ChevronRightIcon /> : <ChevronDownIcon />;
},

getTreeNode() {
const treeData = this.$refs.table.getTreeNode();
console.log(treeData);
this.$message.success('树形结构获取成功,请打开控制台查看');
},

onExpandAllToggle() {
this.expandAll = !this.expandAll;
this.expandAll ? this.$refs.table.expandAll() : this.$refs.table.foldAll();
},

appendToRoot() {
const key = Math.round(Math.random() * 10010);
this.$refs.table.appendTo('', {
id: key,
key: `我是 ${key}_${1} 号`,
platform: key % 2 === 0 ? '共有' : '私有',
type: ['String', 'Number', 'Array', 'Object'][key % 4],
default: ['-', '0', '[]', '{}'][key % 4],
detail: {
position: `读取 ${key} 个数据的嵌套信息值`,
},
needed: key % 4 === 0 ? '是' : '否',
description: '数据源',
});
},

onAbnormalDragSort(params) {
console.log(params);
// this.$message.warning(params.reason);
Expand All @@ -285,10 +313,15 @@ export default {
}
},

// 拖拽排序成功后触发
onDragSort(params) {
console.log('onDragSort:', params);
},

// 应用于需要阻止拖拽排序的场景。如:当子节点存在时,则不允许调整顺序
// 返回值为 true,允许拖拽排序;返回值 为 false,则阻止拖拽排序
beforeDragSort(params) {
console.log(params);
console.log('beforeDragSort:', params);
return true;
},
},
Expand Down
4 changes: 2 additions & 2 deletions examples/table/table.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,14 +172,14 @@ tree | Object | - | 树形结构相关配置。具体属性文档查看 `TableTr
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
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>; trigger?: 'expand-fold-icon' }`<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/>
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>; trigger?: 'expand-fold-icon' }`<br/>

### EnhancedTableInstanceFunctions 组件实例方法

Expand Down
6 changes: 3 additions & 3 deletions src/common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/** Vue2 特有全局变量 */
/** Vue2 特有全局类型 */

export type TNodeReturnValue = import('vue/types/vnode').ScopedSlotReturnValue;
export type TNode<T = undefined> = T extends undefined
Expand All @@ -10,7 +10,7 @@ export type JsxNode = TNodeReturnValue;
export type AttachNodeReturnValue = HTMLElement | Element | Document;
export type AttachNode = CSSSelector | ((triggerNode?: HTMLElement) => AttachNodeReturnValue);

// 与滚动相关的容器类型,因为 document 上没有 scroll 相关属性, 因此排除document
// 与滚动相关的容器类型,因为 document 上没有 scroll 相关属性, 因此排除 document
export type ScrollContainerElement = Window | HTMLElement;
export type ScrollContainer = (() => ScrollContainerElement) | CSSSelector;

Expand All @@ -21,7 +21,7 @@ export type FormSubmitEvent = Event;
export interface Styles {
[css: string]: string | number;
}
/** 通用全局变量 */
/** 通用全局类型 */

export type OptionData = {
label?: string;
Expand Down
16 changes: 9 additions & 7 deletions src/table/enhanced-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,17 @@ export default defineComponent({
return isTreeData ? props.columns : getColumns(props.columns);
});

const onDragSortChange = (context: DragSortContext<TableRowData>) => {
if (props.beforeDragSort && !props.beforeDragSort(context)) return;
const onDragSortChange = (params: DragSortContext<TableRowData>) => {
if (props.beforeDragSort && !props.beforeDragSort(params)) return;
swapData({
current: context.current,
target: context.target,
currentIndex: context.currentIndex,
targetIndex: context.targetIndex,
current: params.current,
target: params.target,
currentIndex: params.currentIndex,
targetIndex: params.targetIndex,
});
props.onDragSort?.(context);
props.onDragSort?.(params);
// Vue3 do not need next line
context.emit('drag-sort', params);
};

return {
Expand Down
62 changes: 60 additions & 2 deletions src/table/hooks/tree-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,27 @@ class TableTreeStore<T extends TableRowData = TableRowData> {
return dataSource;
}

appendToRoot(newData: T, dataSource: T[], keys: KeysType) {
const rowValue = get(newData, keys.rowKey);
if (!rowValue) {
log.error('Table', '`rowKey` could be wrong, can not get rowValue from `data` by `rowKey`.');
return;
}
dataSource.push(newData);
const state: TableRowState = {
id: rowValue,
row: newData,
rowIndex: dataSource.length - 1,
level: 0,
expanded: false,
expandChildrenLength: 0,
disabled: false,
};
state.path = [state];
this.treeDataMap.set(rowValue, state);
return dataSource;
}

/**
* 在当前节点后,插入一个兄弟节点
* @param rowValue 当前节点唯一标识
Expand Down Expand Up @@ -386,11 +407,13 @@ class TableTreeStore<T extends TableRowData = TableRowData> {
if (!parentExpanded) {
newData.push(item);
}
this.treeDataMap.set(rowValue, state);
if (children?.length && !originalExpanded) {
// 同步更新父元素的展开数量
let tmpParent = parent;
while (tmpParent) {
while (tmpParent?.row) {
tmpParent.expandChildrenLength += children.length;
this.treeDataMap.set(tmpParent.id, tmpParent);
tmpParent = tmpParent.parent;
}
// 继续子元素
Expand Down Expand Up @@ -419,12 +442,28 @@ class TableTreeStore<T extends TableRowData = TableRowData> {
}
const children = get(item, keys.childrenKey);
if (children?.length) {
this.expandAll(children, keys);
this.foldAll(children, keys);
}
}
return newData;
}

/** 获取整个树形结构 */
getTreeNode(dataSource: T[], keys: KeysType): T[] {
// let isStarted = false;
const treeData: T[] = [];
for (let i = 0, len = dataSource.length; i < len; i++) {
const item = dataSource[i];
const rowValue = get(item, keys.rowKey);
const state = this.treeDataMap.get(rowValue);
// 只需要压入第一层数据
if (state.level === 0) {
treeData.push(item);
}
}
return treeData;
}

/**
* 初始化树形结构 Map
* @param treeDataMap 树形结构 Map
Expand Down Expand Up @@ -469,6 +508,25 @@ class TableTreeStore<T extends TableRowData = TableRowData> {
}
}

// column.checkProps 和 column.disabled 会影响行的禁用状态,因此当列发生变化时,需要重置禁用状态
updateDisabledState(dataSource: T[], column: PrimaryTableCol, keys: KeysType) {
for (let i = 0, len = dataSource.length; i < len; i++) {
const item = dataSource[i];
const rowValue = get(item, keys.rowKey);
if (rowValue === undefined) {
log.error('EnhancedTable', '`rowKey` could be wrong, can not get rowValue from `data` by `rowKey`.');
return;
}
const state = this.treeDataMap.get(rowValue);
state.disabled = isRowSelectedDisabled(column, item, i);
this.treeDataMap.set(rowValue, state);
const children = get(item, keys.childrenKey);
if (children?.length) {
this.updateDisabledState(children, column, keys);
}
}
}

/**
* 校验数据合法性
*/
Expand Down
4 changes: 2 additions & 2 deletions src/table/hooks/useDragSort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ export default function useDragSort(props: TdPrimaryTableProps, context: SetupCo
const { oldIndex: currentIndex, newIndex: targetIndex } = evt;
const params: DragSortContext<TableRowData> = {
currentIndex,
current: props.data[currentIndex],
current: data.value[currentIndex],
targetIndex,
target: props.data[targetIndex],
target: data.value[targetIndex],
currentData: swapDragArrayElement(props.data, currentIndex, targetIndex),
e: evt,
sort: 'row',
Expand Down
48 changes: 34 additions & 14 deletions src/table/hooks/useTreeData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ export default function useTreeData(props: TdEnhancedTableProps, context: SetupC
childrenKey: props.tree?.childrenKey || 'children',
}));

const checkedColumn = computed(() => columns.value.find((col) => col.colKey === 'row-select'));

watch(checkedColumn, (column) => {
if (!store.value) return;
store.value.updateDisabledState(dataSource.value, column, rowDataKeys.value);
});

function getFoldIcon(h: CreateElement) {
const params = { type: 'fold' };
const defaultFoldIcon = t(global.value.treeExpandAndFoldIcon, h, params) || <MinusRectangleIcon />;
Expand Down Expand Up @@ -95,19 +102,19 @@ export default function useTreeData(props: TdEnhancedTableProps, context: SetupC
* 组件实例方法,展开或收起某一行
* @param p 行数据
*/
function toggleExpandData(p: { row: TableRowData; rowIndex: number; trigger?: 'inner' }) {
function toggleExpandData(p: { row: TableRowData; rowIndex: number }, trigger?: 'expand-fold-icon') {
dataSource.value = store.value.toggleExpandData(p, dataSource.value, rowDataKeys.value);
if (p?.trigger === 'inner') {
const rowValue = get(p.row, rowDataKeys.value.rowKey);
const params = {
row: p.row,
rowIndex: p.rowIndex,
rowState: store.value?.treeDataMap?.get(rowValue),
};
props.onTreeExpandChange?.(params);
// Vue3 ignore next line
context.emit('tree-expand-change', params);
}
const rowValue = get(p.row, rowDataKeys.value.rowKey);
const rowState = store.value?.treeDataMap?.get(rowValue);
const params = {
row: p.row,
rowIndex: p.rowIndex,
rowState,
trigger,
};
props.onTreeExpandChange?.(params);
// Vue3 ignore next line
context.emit('tree-expand-change', params);
}

function getTreeNodeColumnCol() {
Expand Down Expand Up @@ -139,7 +146,7 @@ export default function useTreeData(props: TdEnhancedTableProps, context: SetupC
return (
<div class={[tableTreeClasses.col, classes]} style={colStyle}>
{!!childrenNodes.length && (
<span class={tableTreeClasses.icon} onClick={() => toggleExpandData({ ...p, trigger: 'inner' })}>
<span class={tableTreeClasses.icon} onClick={() => toggleExpandData(p, 'expand-fold-icon')}>
{iconNode}
</span>
)}
Expand Down Expand Up @@ -195,7 +202,11 @@ export default function useTreeData(props: TdEnhancedTableProps, context: SetupC
* @param key 当前节点唯一标识
* @param newData 待添加的新节点
*/
function appendTo<T>(key: TableRowValue, newData: T) {
function appendTo<T>(key: TableRowValue = '', newData: T) {
if (!key) {
dataSource.value = store.value.appendToRoot(newData, dataSource.value, rowDataKeys.value);
return;
}
// 引用传值,可自动更新 dataSource。(dataSource 本是内部变量,可以在任何地方进行任何改变)
dataSource.value = [...store.value.appendTo(key, newData, dataSource.value, rowDataKeys.value)];
}
Expand Down Expand Up @@ -246,6 +257,14 @@ export default function useTreeData(props: TdEnhancedTableProps, context: SetupC
}
}

/**
* 获取全部数据的树形结构
* @param key 节点唯一标识
*/
function getTreeNode() {
return store.value.getTreeNode(dataSource.value, rowDataKeys.value);
}

return {
store,
rowDataKeys,
Expand All @@ -261,5 +280,6 @@ export default function useTreeData(props: TdEnhancedTableProps, context: SetupC
toggleExpandData,
expandAll,
foldAll,
getTreeNode,
};
}
1 change: 1 addition & 0 deletions src/table/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,7 @@ export interface TableTreeExpandChangeContext<T> {
row: T;
rowIndex: number;
rowState: TableRowState<T>;
trigger?: 'expand-fold-icon';
}

export type TableRowValue = string | number;
Expand Down
3 changes: 2 additions & 1 deletion test/ssr/__snapshots__/ssr.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -15263,7 +15263,8 @@ exports[`ssr snapshot test renders ./examples/table/demos/single-sort.vue correc

exports[`ssr snapshot test renders ./examples/table/demos/tree.vue correctly 1`] = `
<div>
<div><button type="button" class="t-button t-size-m t-button--variant-base t-button--theme-default"><span class="t-button__text">重置数据</span></button> <button type="button" class="t-button t-size-m t-button--variant-base t-button--theme-default" style="margin-left:16px;"><span class="t-button__text">任意节点展开/收起</span></button> <button type="button" class="t-button t-size-m t-button--variant-base t-button--theme-default" style="margin-left:16px;"><span class="t-button__text">展开全部</span></button> <label class="t-checkbox" style="margin-left:16px;vertical-align:middle;"><input type="checkbox" class="t-checkbox__former"><span class="t-checkbox__input"></span><span class="t-checkbox__label">
<div><button type="button" class="t-button t-size-m t-button--variant-base t-button--theme-primary"><span class="t-button__text">添加根节点</span></button> <button type="button" class="t-button t-size-m t-button--variant-base t-button--theme-default" style="margin-left:16px;"><span class="t-button__text">重置数据</span></button> <button type="button" class="t-button t-size-m t-button--variant-base t-button--theme-default" style="margin-left:16px;"><span class="t-button__text">任意节点展开/收起</span></button> <button type="button" class="t-button t-size-m t-button--variant-base t-button--theme-default" style="margin-left:16px;"><span class="t-button__text">展开全部</span></button> <button type="button" class="t-button t-size-m t-button--variant-base t-button--theme-default" style="margin-left:16px;"><span class="t-button__text">获取全部树形结构</span></button></div> <br>
<div><label class="t-checkbox" style="vertical-align:middle;"><input type="checkbox" class="t-checkbox__former"><span class="t-checkbox__input"></span><span class="t-checkbox__label">
自定义折叠/展开图标
</span></label></div> <br>
<div class="t-table t-table--row-handler-draggable" style="position:relative;">
Expand Down
Loading