stk-table-vue 1.2.4 → 1.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +194 -194
- package/lib/{Dropdown-D_9cB0rD.js → Dropdown-BAANgg_5.js} +2 -2
- package/lib/{StkTable-CVcmlZi9.js → StkTable-CGcxwpdb.js} +22 -6
- package/lib/src/StkTable/StkTable.vue.d.ts +18 -4
- package/lib/src/StkTable/types/index.d.ts +4 -1
- package/lib/src/StkTable/useVirtualScroll.d.ts +6 -1
- package/lib/stk-table-vue.js +3 -3
- package/lib/style.css +1 -1
- package/package.json +93 -93
- package/src/StkTable/StkTable.vue +2362 -2338
- package/src/StkTable/components/DragHandle.vue +9 -9
- package/src/StkTable/components/SortIcon.vue +6 -6
- package/src/StkTable/components/TreeNodeCell.vue +19 -19
- package/src/StkTable/components/TriangleIcon.vue +3 -3
- package/src/StkTable/const.ts +50 -50
- package/src/StkTable/custom-cells/ChangeCell/ChangeCell.less +34 -34
- package/src/StkTable/custom-cells/ChangeCell/createChangeCell.ts +90 -90
- package/src/StkTable/custom-cells/ChangeCell/index.ts +4 -4
- package/src/StkTable/custom-cells/CheckboxCell/CheckboxCell.less +14 -14
- package/src/StkTable/custom-cells/CheckboxCell/CheckboxCell.vue +56 -56
- package/src/StkTable/custom-cells/CheckboxCell/createCheckboxCell.ts +146 -146
- package/src/StkTable/custom-cells/CheckboxCell/index.ts +5 -5
- package/src/StkTable/custom-cells/FilterCell/Dropdown/index.ts +16 -16
- package/src/StkTable/custom-cells/FilterCell/Dropdown/index.vue +186 -186
- package/src/StkTable/custom-cells/FilterCell/Filter.less +118 -118
- package/src/StkTable/custom-cells/FilterCell/Filter.vue +66 -66
- package/src/StkTable/custom-cells/FilterCell/createFilterCell.ts +120 -120
- package/src/StkTable/custom-cells/FilterCell/index.ts +6 -6
- package/src/StkTable/custom-cells/FilterCell/types.ts +43 -43
- package/src/StkTable/custom-cells/NumberCell/createNumberCell.ts +43 -43
- package/src/StkTable/custom-cells/NumberCell/index.ts +2 -2
- package/src/StkTable/custom-cells/utils/formatNumber.ts +137 -137
- package/src/StkTable/features/const.ts +1 -1
- package/src/StkTable/features/index.ts +1 -1
- package/src/StkTable/features/useAreaSelection.ts +1240 -1239
- package/src/StkTable/index.ts +20 -20
- package/src/StkTable/mergeCellsCache.ts +69 -69
- package/src/StkTable/registerFeature.ts +40 -40
- package/src/StkTable/style.less +791 -791
- package/src/StkTable/types/highlightDimOptions.ts +28 -28
- package/src/StkTable/types/index.ts +503 -500
- package/src/StkTable/useAutoResize.ts +87 -87
- package/src/StkTable/useColResize.ts +202 -202
- package/src/StkTable/useFixedCol.ts +168 -168
- package/src/StkTable/useFixedStyle.ts +75 -75
- package/src/StkTable/useGetFixedColPosition.ts +63 -63
- package/src/StkTable/useHighlight.ts +270 -270
- package/src/StkTable/useIndexResolver.ts +29 -29
- package/src/StkTable/useKeyboardArrowScroll.ts +114 -114
- package/src/StkTable/useMaxRowSpan.ts +60 -60
- package/src/StkTable/useMergeCells.ts +541 -541
- package/src/StkTable/useRowExpand.ts +81 -81
- package/src/StkTable/useScrollRowByRow.ts +96 -96
- package/src/StkTable/useScrollbar.ts +177 -177
- package/src/StkTable/useSorter.ts +267 -267
- package/src/StkTable/useTableColumns.ts +142 -142
- package/src/StkTable/useThDrag.ts +94 -94
- package/src/StkTable/useTrDrag.ts +100 -100
- package/src/StkTable/useTree.ts +253 -253
- package/src/StkTable/useVirtualScroll.ts +1032 -1025
- package/src/StkTable/useWheeling.ts +23 -23
- package/src/StkTable/utils/constRefUtils.ts +29 -29
- package/src/StkTable/utils/index.ts +331 -331
- package/src/StkTable/utils/rowHeightFenwickTree.ts +74 -74
- package/src/StkTable/utils/useTriggerRef.ts +33 -33
- package/src/VirtualTree.vue +622 -622
- package/src/VirtualTreeSelect.vue +367 -367
- package/src/vite-env.d.ts +10 -10
package/src/StkTable/useTree.ts
CHANGED
|
@@ -1,253 +1,253 @@
|
|
|
1
|
-
import { ShallowRef } from 'vue';
|
|
2
|
-
import { PrivateRowDT, RowKeyGen, TreeConfig, UniqKey } from './types';
|
|
3
|
-
|
|
4
|
-
type DT = PrivateRowDT & { children?: DT[] };
|
|
5
|
-
|
|
6
|
-
type SetTreeExpandOption = {
|
|
7
|
-
/**
|
|
8
|
-
* 是否展开
|
|
9
|
-
* en: Whether to expand
|
|
10
|
-
* @default false
|
|
11
|
-
*/
|
|
12
|
-
expand?: boolean;
|
|
13
|
-
/**
|
|
14
|
-
* 是否展开所有子节点
|
|
15
|
-
* en: Whether to expand all child nodes
|
|
16
|
-
* @default false
|
|
17
|
-
* @version 1.0.4
|
|
18
|
-
*/
|
|
19
|
-
all?: boolean;
|
|
20
|
-
/**
|
|
21
|
-
* 展开到第几层
|
|
22
|
-
* en: Expand to the nth level
|
|
23
|
-
* @version 1.0.4
|
|
24
|
-
*/
|
|
25
|
-
level?: number;
|
|
26
|
-
/**
|
|
27
|
-
* 将传入 row 视为目标子节点,展开/收起其所有父节点;展开时若目标行自身有子节点则一并展开
|
|
28
|
-
* en: Treat the given row as a target child, expand/collapse all its ancestors. The target row itself is also expanded when expanding if it has children
|
|
29
|
-
* @version 1.1.0
|
|
30
|
-
*/
|
|
31
|
-
parents?: boolean;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export function useTree(props: any, dataSourceCopy: ShallowRef<DT[]>, rowKeyGen: RowKeyGen, emits: any, onDataSourceChange: () => void) {
|
|
35
|
-
const { defaultExpandAll, defaultExpandKeys, defaultExpandLevel }: TreeConfig = props.treeConfig;
|
|
36
|
-
/** It used to check if it is first load. To execute defaultExpandXXX */
|
|
37
|
-
let isFirstLoad = true;
|
|
38
|
-
/** click expended icon to toggle expand row */
|
|
39
|
-
function toggleTreeNode(row: DT, col: any) {
|
|
40
|
-
const expand = row ? !row.__T_EXP__ : false;
|
|
41
|
-
privateSetTreeExpand(row, { expand, col, isClick: true });
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
*
|
|
46
|
-
* @param row rowKey or row
|
|
47
|
-
* @param option
|
|
48
|
-
* @param option.expand expand or collapse
|
|
49
|
-
* @param option.all expand all descendants
|
|
50
|
-
* @param option.level expand to the nth level
|
|
51
|
-
* @param option.parents expand/collapse all ancestors of the given row, the target row itself is also expanded if it has children
|
|
52
|
-
* @param option.silent if set true, not emit `toggle-tree-expand`, default:false
|
|
53
|
-
*/
|
|
54
|
-
function privateSetTreeExpand(row: (UniqKey | DT) | (UniqKey | DT)[], option: SetTreeExpandOption & { col?: any; isClick: boolean }) {
|
|
55
|
-
const rowKeyOrRowArr: (UniqKey | DT)[] = Array.isArray(row) ? row : [row];
|
|
56
|
-
|
|
57
|
-
const tempData = dataSourceCopy.value.slice();
|
|
58
|
-
for (let i = 0; i < rowKeyOrRowArr.length; i++) {
|
|
59
|
-
const rowKeyOrRow = rowKeyOrRowArr[i];
|
|
60
|
-
let rowKey: UniqKey;
|
|
61
|
-
if (typeof rowKeyOrRow === 'string' || typeof rowKeyOrRow === 'number') {
|
|
62
|
-
rowKey = rowKeyOrRow;
|
|
63
|
-
} else {
|
|
64
|
-
rowKey = rowKeyGen(rowKeyOrRow);
|
|
65
|
-
}
|
|
66
|
-
const index = tempData.findIndex(it => rowKeyGen(it) === rowKey);
|
|
67
|
-
if (index === -1) {
|
|
68
|
-
console.warn('treeExpandRow failed.rowKey:', rowKey);
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const row = tempData[index];
|
|
73
|
-
const level = row.__T_LV__ || 0;
|
|
74
|
-
const wasExpanded = Boolean(row.__T_EXP__);
|
|
75
|
-
let expanded = option?.expand;
|
|
76
|
-
if (expanded === void 0) {
|
|
77
|
-
expanded = !row.__T_EXP__;
|
|
78
|
-
}
|
|
79
|
-
if (option.all || option.level !== void 0) {
|
|
80
|
-
const targetLevel = option.all ? Infinity : option.level || 0;
|
|
81
|
-
setDescendantsToLevel(row, level + 1, targetLevel, expanded);
|
|
82
|
-
}
|
|
83
|
-
if (expanded) {
|
|
84
|
-
if (wasExpanded) {
|
|
85
|
-
// already expanded, rebuild the flattened subtree so newly expanded
|
|
86
|
-
// descendants are inserted into the visible data source
|
|
87
|
-
const deleteCount = foldNode(index, tempData, level);
|
|
88
|
-
const children = expandNode(row, level);
|
|
89
|
-
tempData.splice(index + 1, deleteCount, ...children);
|
|
90
|
-
} else {
|
|
91
|
-
const children = expandNode(row, level);
|
|
92
|
-
tempData.splice(index + 1, 0, ...children);
|
|
93
|
-
}
|
|
94
|
-
} else {
|
|
95
|
-
// delete all child nodes from i
|
|
96
|
-
const deleteCount = foldNode(index, tempData, level);
|
|
97
|
-
tempData.splice(index + 1, deleteCount);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
setNodeExpanded(row, expanded, level);
|
|
101
|
-
|
|
102
|
-
if (option.isClick) {
|
|
103
|
-
emits('toggle-tree-expand', { expanded: Boolean(expanded), row, col: option.col });
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
dataSourceCopy.value = tempData;
|
|
108
|
-
onDataSourceChange();
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function setTreeExpand(row: (UniqKey | DT) | (UniqKey | DT)[], option?: SetTreeExpandOption) {
|
|
112
|
-
if (option?.parents) {
|
|
113
|
-
const rowKeyOrRow = Array.isArray(row) ? row[0] : row;
|
|
114
|
-
const rowKey = typeof rowKeyOrRow === 'string' || typeof rowKeyOrRow === 'number' ? rowKeyOrRow : rowKeyGen(rowKeyOrRow);
|
|
115
|
-
const path = findPath(props.dataSource || [], rowKey);
|
|
116
|
-
if (!path) {
|
|
117
|
-
console.warn('treeExpandRow failed.rowKey:', rowKey);
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
const expanded = option?.expand !== false;
|
|
121
|
-
const target = path[path.length - 1];
|
|
122
|
-
const keys = path.slice(0, -1).map(it => rowKeyGen(it));
|
|
123
|
-
// 展开时若目标行自身有子节点则一并展开;收起时仅处理父节点,目标行自身状态不变
|
|
124
|
-
// en: when expanding, also expand the target row itself if it has children; when collapsing, only ancestors are handled
|
|
125
|
-
if (expanded && target.children?.length) keys.push(rowKeyGen(target));
|
|
126
|
-
if (!keys.length) return;
|
|
127
|
-
// 展开时从根到目标逐级展开;收起时逆序处理,避免先折叠根节点导致其余节点从可见数据中移除而查找失败
|
|
128
|
-
// en: expand from root to target; collapse in reverse order, otherwise collapsing the root first removes the rest nodes from visible data
|
|
129
|
-
if (!expanded) keys.reverse();
|
|
130
|
-
privateSetTreeExpand(keys, { expand: expanded, isClick: false });
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
privateSetTreeExpand(row, { ...option, isClick: false });
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* 在原始树形数据中查找目标节点,返回从根节点到目标节点的完整路径(含目标节点自身)
|
|
138
|
-
* en: Find target node in raw tree data, return the full path from root to target node (target included)
|
|
139
|
-
* @returns full path including target, or null if target not found
|
|
140
|
-
*/
|
|
141
|
-
function findPath(data: DT[], targetKey: UniqKey): DT[] | null {
|
|
142
|
-
const path: DT[] = [];
|
|
143
|
-
function dfs(list: DT[]): boolean {
|
|
144
|
-
for (const item of list) {
|
|
145
|
-
if (rowKeyGen(item) === targetKey) {
|
|
146
|
-
path.push(item);
|
|
147
|
-
return true;
|
|
148
|
-
}
|
|
149
|
-
if (item.children) {
|
|
150
|
-
path.push(item);
|
|
151
|
-
if (dfs(item.children)) return true;
|
|
152
|
-
path.pop();
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
return dfs(data) ? path : null;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function setNodeExpanded(row: DT, expanded: boolean, level?: number, parent?: DT) {
|
|
161
|
-
row.__T_EXP__ = expanded;
|
|
162
|
-
if (level !== void 0) {
|
|
163
|
-
row.__T_LV__ = level;
|
|
164
|
-
}
|
|
165
|
-
// if (parent) {
|
|
166
|
-
// row.__T_P_K__ = rowKeyGen(parent);
|
|
167
|
-
// }
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function recursionFlat(data: DT[] | undefined, level: number, parent?: DT): DT[] {
|
|
171
|
-
if (!data) return [];
|
|
172
|
-
let result: DT[] = [];
|
|
173
|
-
for (let i = 0; i < data.length; i++) {
|
|
174
|
-
const item = data[i];
|
|
175
|
-
result.push(item);
|
|
176
|
-
const isExpanded = Boolean(item.__T_EXP__);
|
|
177
|
-
setNodeExpanded(item, isExpanded, level, parent);
|
|
178
|
-
if (isFirstLoad && !isExpanded) {
|
|
179
|
-
// first load will expand all node if defaultExpandAll is true
|
|
180
|
-
if (defaultExpandAll) {
|
|
181
|
-
setNodeExpanded(item, true);
|
|
182
|
-
} else {
|
|
183
|
-
if (defaultExpandLevel && level < defaultExpandLevel) {
|
|
184
|
-
setNodeExpanded(item, true);
|
|
185
|
-
}
|
|
186
|
-
if (defaultExpandKeys?.includes(rowKeyGen(item))) {
|
|
187
|
-
setNodeExpanded(item, true);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
if (item.__T_EXP__) {
|
|
192
|
-
const res = recursionFlat(item.children, level + 1, item);
|
|
193
|
-
result = result.concat(res);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return result;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* 根据保存的展开状态,深度遍历,展平树形数据。
|
|
201
|
-
* en: flatten tree data by saved expand state.
|
|
202
|
-
* @param data
|
|
203
|
-
* @returns
|
|
204
|
-
*/
|
|
205
|
-
function flatTreeData(data: DT[]) {
|
|
206
|
-
const result = recursionFlat(data, 0);
|
|
207
|
-
isFirstLoad = false;
|
|
208
|
-
return result;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* 递归设置目标节点后代到指定层级的展开/折叠状态
|
|
213
|
-
* en: Recursively set expand/collapse state for descendants up to the target level
|
|
214
|
-
*/
|
|
215
|
-
function setDescendantsToLevel(row: DT, currentLevel: number, targetLevel: number, expanded: boolean) {
|
|
216
|
-
if (!row.children || currentLevel > targetLevel) return;
|
|
217
|
-
for (const child of row.children) {
|
|
218
|
-
setNodeExpanded(child, expanded, currentLevel, row);
|
|
219
|
-
setDescendantsToLevel(child, currentLevel + 1, targetLevel, expanded);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
function expandNode(row: DT, level: number) {
|
|
224
|
-
let result: DT[] = [];
|
|
225
|
-
row.children &&
|
|
226
|
-
row.children.forEach((child: DT) => {
|
|
227
|
-
result.push(child);
|
|
228
|
-
const childLv = level + 1;
|
|
229
|
-
if (child.__T_EXP__ && child.children) {
|
|
230
|
-
const res = expandNode(child, childLv);
|
|
231
|
-
result = result.concat(res);
|
|
232
|
-
} else {
|
|
233
|
-
setNodeExpanded(child, false, childLv, row);
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
return result;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
function foldNode(index: number, tempData: DT[], level: number) {
|
|
240
|
-
let deleteCount = 0;
|
|
241
|
-
for (let i = index + 1; i < tempData.length; i++) {
|
|
242
|
-
const child = tempData[i];
|
|
243
|
-
if (child.__T_LV__ && child.__T_LV__ > level) {
|
|
244
|
-
deleteCount++;
|
|
245
|
-
} else {
|
|
246
|
-
break;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
return deleteCount;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
return [toggleTreeNode, setTreeExpand, flatTreeData] as const;
|
|
253
|
-
}
|
|
1
|
+
import { ShallowRef } from 'vue';
|
|
2
|
+
import { PrivateRowDT, RowKeyGen, TreeConfig, UniqKey } from './types';
|
|
3
|
+
|
|
4
|
+
type DT = PrivateRowDT & { children?: DT[] };
|
|
5
|
+
|
|
6
|
+
type SetTreeExpandOption = {
|
|
7
|
+
/**
|
|
8
|
+
* 是否展开
|
|
9
|
+
* en: Whether to expand
|
|
10
|
+
* @default false
|
|
11
|
+
*/
|
|
12
|
+
expand?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* 是否展开所有子节点
|
|
15
|
+
* en: Whether to expand all child nodes
|
|
16
|
+
* @default false
|
|
17
|
+
* @version 1.0.4
|
|
18
|
+
*/
|
|
19
|
+
all?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* 展开到第几层
|
|
22
|
+
* en: Expand to the nth level
|
|
23
|
+
* @version 1.0.4
|
|
24
|
+
*/
|
|
25
|
+
level?: number;
|
|
26
|
+
/**
|
|
27
|
+
* 将传入 row 视为目标子节点,展开/收起其所有父节点;展开时若目标行自身有子节点则一并展开
|
|
28
|
+
* en: Treat the given row as a target child, expand/collapse all its ancestors. The target row itself is also expanded when expanding if it has children
|
|
29
|
+
* @version 1.1.0
|
|
30
|
+
*/
|
|
31
|
+
parents?: boolean;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export function useTree(props: any, dataSourceCopy: ShallowRef<DT[]>, rowKeyGen: RowKeyGen, emits: any, onDataSourceChange: () => void) {
|
|
35
|
+
const { defaultExpandAll, defaultExpandKeys, defaultExpandLevel }: TreeConfig = props.treeConfig;
|
|
36
|
+
/** It used to check if it is first load. To execute defaultExpandXXX */
|
|
37
|
+
let isFirstLoad = true;
|
|
38
|
+
/** click expended icon to toggle expand row */
|
|
39
|
+
function toggleTreeNode(row: DT, col: any) {
|
|
40
|
+
const expand = row ? !row.__T_EXP__ : false;
|
|
41
|
+
privateSetTreeExpand(row, { expand, col, isClick: true });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
* @param row rowKey or row
|
|
47
|
+
* @param option
|
|
48
|
+
* @param option.expand expand or collapse
|
|
49
|
+
* @param option.all expand all descendants
|
|
50
|
+
* @param option.level expand to the nth level
|
|
51
|
+
* @param option.parents expand/collapse all ancestors of the given row, the target row itself is also expanded if it has children
|
|
52
|
+
* @param option.silent if set true, not emit `toggle-tree-expand`, default:false
|
|
53
|
+
*/
|
|
54
|
+
function privateSetTreeExpand(row: (UniqKey | DT) | (UniqKey | DT)[], option: SetTreeExpandOption & { col?: any; isClick: boolean }) {
|
|
55
|
+
const rowKeyOrRowArr: (UniqKey | DT)[] = Array.isArray(row) ? row : [row];
|
|
56
|
+
|
|
57
|
+
const tempData = dataSourceCopy.value.slice();
|
|
58
|
+
for (let i = 0; i < rowKeyOrRowArr.length; i++) {
|
|
59
|
+
const rowKeyOrRow = rowKeyOrRowArr[i];
|
|
60
|
+
let rowKey: UniqKey;
|
|
61
|
+
if (typeof rowKeyOrRow === 'string' || typeof rowKeyOrRow === 'number') {
|
|
62
|
+
rowKey = rowKeyOrRow;
|
|
63
|
+
} else {
|
|
64
|
+
rowKey = rowKeyGen(rowKeyOrRow);
|
|
65
|
+
}
|
|
66
|
+
const index = tempData.findIndex(it => rowKeyGen(it) === rowKey);
|
|
67
|
+
if (index === -1) {
|
|
68
|
+
console.warn('treeExpandRow failed.rowKey:', rowKey);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const row = tempData[index];
|
|
73
|
+
const level = row.__T_LV__ || 0;
|
|
74
|
+
const wasExpanded = Boolean(row.__T_EXP__);
|
|
75
|
+
let expanded = option?.expand;
|
|
76
|
+
if (expanded === void 0) {
|
|
77
|
+
expanded = !row.__T_EXP__;
|
|
78
|
+
}
|
|
79
|
+
if (option.all || option.level !== void 0) {
|
|
80
|
+
const targetLevel = option.all ? Infinity : option.level || 0;
|
|
81
|
+
setDescendantsToLevel(row, level + 1, targetLevel, expanded);
|
|
82
|
+
}
|
|
83
|
+
if (expanded) {
|
|
84
|
+
if (wasExpanded) {
|
|
85
|
+
// already expanded, rebuild the flattened subtree so newly expanded
|
|
86
|
+
// descendants are inserted into the visible data source
|
|
87
|
+
const deleteCount = foldNode(index, tempData, level);
|
|
88
|
+
const children = expandNode(row, level);
|
|
89
|
+
tempData.splice(index + 1, deleteCount, ...children);
|
|
90
|
+
} else {
|
|
91
|
+
const children = expandNode(row, level);
|
|
92
|
+
tempData.splice(index + 1, 0, ...children);
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
// delete all child nodes from i
|
|
96
|
+
const deleteCount = foldNode(index, tempData, level);
|
|
97
|
+
tempData.splice(index + 1, deleteCount);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
setNodeExpanded(row, expanded, level);
|
|
101
|
+
|
|
102
|
+
if (option.isClick) {
|
|
103
|
+
emits('toggle-tree-expand', { expanded: Boolean(expanded), row, col: option.col });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
dataSourceCopy.value = tempData;
|
|
108
|
+
onDataSourceChange();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function setTreeExpand(row: (UniqKey | DT) | (UniqKey | DT)[], option?: SetTreeExpandOption) {
|
|
112
|
+
if (option?.parents) {
|
|
113
|
+
const rowKeyOrRow = Array.isArray(row) ? row[0] : row;
|
|
114
|
+
const rowKey = typeof rowKeyOrRow === 'string' || typeof rowKeyOrRow === 'number' ? rowKeyOrRow : rowKeyGen(rowKeyOrRow);
|
|
115
|
+
const path = findPath(props.dataSource || [], rowKey);
|
|
116
|
+
if (!path) {
|
|
117
|
+
console.warn('treeExpandRow failed.rowKey:', rowKey);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const expanded = option?.expand !== false;
|
|
121
|
+
const target = path[path.length - 1];
|
|
122
|
+
const keys = path.slice(0, -1).map(it => rowKeyGen(it));
|
|
123
|
+
// 展开时若目标行自身有子节点则一并展开;收起时仅处理父节点,目标行自身状态不变
|
|
124
|
+
// en: when expanding, also expand the target row itself if it has children; when collapsing, only ancestors are handled
|
|
125
|
+
if (expanded && target.children?.length) keys.push(rowKeyGen(target));
|
|
126
|
+
if (!keys.length) return;
|
|
127
|
+
// 展开时从根到目标逐级展开;收起时逆序处理,避免先折叠根节点导致其余节点从可见数据中移除而查找失败
|
|
128
|
+
// en: expand from root to target; collapse in reverse order, otherwise collapsing the root first removes the rest nodes from visible data
|
|
129
|
+
if (!expanded) keys.reverse();
|
|
130
|
+
privateSetTreeExpand(keys, { expand: expanded, isClick: false });
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
privateSetTreeExpand(row, { ...option, isClick: false });
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 在原始树形数据中查找目标节点,返回从根节点到目标节点的完整路径(含目标节点自身)
|
|
138
|
+
* en: Find target node in raw tree data, return the full path from root to target node (target included)
|
|
139
|
+
* @returns full path including target, or null if target not found
|
|
140
|
+
*/
|
|
141
|
+
function findPath(data: DT[], targetKey: UniqKey): DT[] | null {
|
|
142
|
+
const path: DT[] = [];
|
|
143
|
+
function dfs(list: DT[]): boolean {
|
|
144
|
+
for (const item of list) {
|
|
145
|
+
if (rowKeyGen(item) === targetKey) {
|
|
146
|
+
path.push(item);
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
if (item.children) {
|
|
150
|
+
path.push(item);
|
|
151
|
+
if (dfs(item.children)) return true;
|
|
152
|
+
path.pop();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
return dfs(data) ? path : null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function setNodeExpanded(row: DT, expanded: boolean, level?: number, parent?: DT) {
|
|
161
|
+
row.__T_EXP__ = expanded;
|
|
162
|
+
if (level !== void 0) {
|
|
163
|
+
row.__T_LV__ = level;
|
|
164
|
+
}
|
|
165
|
+
// if (parent) {
|
|
166
|
+
// row.__T_P_K__ = rowKeyGen(parent);
|
|
167
|
+
// }
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function recursionFlat(data: DT[] | undefined, level: number, parent?: DT): DT[] {
|
|
171
|
+
if (!data) return [];
|
|
172
|
+
let result: DT[] = [];
|
|
173
|
+
for (let i = 0; i < data.length; i++) {
|
|
174
|
+
const item = data[i];
|
|
175
|
+
result.push(item);
|
|
176
|
+
const isExpanded = Boolean(item.__T_EXP__);
|
|
177
|
+
setNodeExpanded(item, isExpanded, level, parent);
|
|
178
|
+
if (isFirstLoad && !isExpanded) {
|
|
179
|
+
// first load will expand all node if defaultExpandAll is true
|
|
180
|
+
if (defaultExpandAll) {
|
|
181
|
+
setNodeExpanded(item, true);
|
|
182
|
+
} else {
|
|
183
|
+
if (defaultExpandLevel && level < defaultExpandLevel) {
|
|
184
|
+
setNodeExpanded(item, true);
|
|
185
|
+
}
|
|
186
|
+
if (defaultExpandKeys?.includes(rowKeyGen(item))) {
|
|
187
|
+
setNodeExpanded(item, true);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (item.__T_EXP__) {
|
|
192
|
+
const res = recursionFlat(item.children, level + 1, item);
|
|
193
|
+
result = result.concat(res);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return result;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 根据保存的展开状态,深度遍历,展平树形数据。
|
|
201
|
+
* en: flatten tree data by saved expand state.
|
|
202
|
+
* @param data
|
|
203
|
+
* @returns
|
|
204
|
+
*/
|
|
205
|
+
function flatTreeData(data: DT[]) {
|
|
206
|
+
const result = recursionFlat(data, 0);
|
|
207
|
+
isFirstLoad = false;
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* 递归设置目标节点后代到指定层级的展开/折叠状态
|
|
213
|
+
* en: Recursively set expand/collapse state for descendants up to the target level
|
|
214
|
+
*/
|
|
215
|
+
function setDescendantsToLevel(row: DT, currentLevel: number, targetLevel: number, expanded: boolean) {
|
|
216
|
+
if (!row.children || currentLevel > targetLevel) return;
|
|
217
|
+
for (const child of row.children) {
|
|
218
|
+
setNodeExpanded(child, expanded, currentLevel, row);
|
|
219
|
+
setDescendantsToLevel(child, currentLevel + 1, targetLevel, expanded);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function expandNode(row: DT, level: number) {
|
|
224
|
+
let result: DT[] = [];
|
|
225
|
+
row.children &&
|
|
226
|
+
row.children.forEach((child: DT) => {
|
|
227
|
+
result.push(child);
|
|
228
|
+
const childLv = level + 1;
|
|
229
|
+
if (child.__T_EXP__ && child.children) {
|
|
230
|
+
const res = expandNode(child, childLv);
|
|
231
|
+
result = result.concat(res);
|
|
232
|
+
} else {
|
|
233
|
+
setNodeExpanded(child, false, childLv, row);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
return result;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function foldNode(index: number, tempData: DT[], level: number) {
|
|
240
|
+
let deleteCount = 0;
|
|
241
|
+
for (let i = index + 1; i < tempData.length; i++) {
|
|
242
|
+
const child = tempData[i];
|
|
243
|
+
if (child.__T_LV__ && child.__T_LV__ > level) {
|
|
244
|
+
deleteCount++;
|
|
245
|
+
} else {
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return deleteCount;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return [toggleTreeNode, setTreeExpand, flatTreeData] as const;
|
|
253
|
+
}
|