@ticatec/uniface-element 0.3.16 → 0.3.17
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/dist/lib/TreeNode_README.md +247 -119
- package/dist/lib/TreeNode_README_CN.md +248 -120
- package/dist/lib/TreeNodes.d.ts +339 -85
- package/dist/lib/TreeNodes.js +376 -206
- package/dist/lib/index.d.ts +3 -4
- package/dist/lib/index.js +1 -2
- package/dist/nav-menu/Menus.d.ts +2 -2
- package/dist/nav-menu/Menus.js +6 -4
- package/dist/ticatec-uniface-web.css +29 -5
- package/dist/tree-view/README.md +131 -6
- package/dist/tree-view/TreeNodeView.svelte +13 -11
- package/dist/tree-view/TreeNodeView.svelte.d.ts +5 -5
- package/dist/tree-view/TreeView.svelte +25 -8
- package/dist/tree-view/TreeView.svelte.d.ts +3 -2
- package/dist/tree-view/Types.d.ts +4 -4
- package/dist/tree-view/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/lib/TreeNodes.js
CHANGED
|
@@ -1,184 +1,376 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 比较两个数字
|
|
3
|
+
* @param a 第一个数字
|
|
4
|
+
* @param b 第二个数字
|
|
5
|
+
* @returns 如果相等返回 0,a > b 返回 1,否则返回 -1
|
|
6
|
+
*/
|
|
1
7
|
export function compareNumber(a, b) {
|
|
2
8
|
return a === b ? 0 : a > b ? 1 : -1;
|
|
3
9
|
}
|
|
4
|
-
|
|
5
|
-
|
|
10
|
+
/**
|
|
11
|
+
* 节点视图配置类 - 定义节点的显示方式
|
|
12
|
+
* @template T 节点数据的类型
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* const options = new NodeViewOptions<MyData>({
|
|
16
|
+
* keyField: 'id',
|
|
17
|
+
* textField: 'name'
|
|
18
|
+
* });
|
|
19
|
+
*/
|
|
20
|
+
export class NodeViewOptions {
|
|
21
|
+
/**
|
|
22
|
+
* 获取节点的唯一标识字段
|
|
23
|
+
*/
|
|
6
24
|
keyField;
|
|
7
|
-
|
|
25
|
+
/**
|
|
26
|
+
* 获取节点的文字
|
|
27
|
+
* 可以是字段名或函数
|
|
28
|
+
*/
|
|
8
29
|
textField;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
_nodes = [];
|
|
14
|
-
_version = 0;
|
|
30
|
+
/**
|
|
31
|
+
* 创建节点视图配置
|
|
32
|
+
* @param options 配置选项
|
|
33
|
+
*/
|
|
15
34
|
constructor(options) {
|
|
16
|
-
this.
|
|
17
|
-
this.
|
|
18
|
-
this.keyField = options.keyField ?? 'id';
|
|
19
|
-
this.textField = options.textField ?? 'text';
|
|
20
|
-
this.parentKeyField = options.parentKeyField ?? 'parentId';
|
|
21
|
-
this.nodeMap = new Map();
|
|
22
|
-
this.expendDepth = options.expendDepth ?? 1;
|
|
23
|
-
this.checkIsDirectory = options.checkIsDirectory;
|
|
35
|
+
this.keyField = options.keyField;
|
|
36
|
+
this.textField = options.textField;
|
|
24
37
|
}
|
|
25
|
-
|
|
26
|
-
|
|
38
|
+
/**
|
|
39
|
+
* 获取节点的文字
|
|
40
|
+
* @param data 节点数据
|
|
41
|
+
* @returns 显示文字
|
|
42
|
+
*/
|
|
43
|
+
getText(data) {
|
|
44
|
+
if (typeof this.textField === 'function') {
|
|
45
|
+
return this.textField(data);
|
|
46
|
+
}
|
|
47
|
+
return String(data[this.textField] ?? '');
|
|
27
48
|
}
|
|
28
49
|
/**
|
|
29
|
-
*
|
|
50
|
+
* 获取节点的唯一标识
|
|
51
|
+
* @param data 节点数据
|
|
52
|
+
* @returns 唯一标识值
|
|
30
53
|
*/
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
item,
|
|
34
|
-
expand: false,
|
|
35
|
-
append: (childItem) => this.addNodeToNode(node, childItem),
|
|
36
|
-
remove: () => this.removeNode(node),
|
|
37
|
-
replace: (newItem) => this.replaceNodeItem(node, newItem),
|
|
38
|
-
moveTo: (newParentId) => this.moveNodeTo(node, newParentId),
|
|
39
|
-
removeChild: (childId) => this.removeChildNode(node, childId),
|
|
40
|
-
removeChildren: () => this.removeChildrenNodes(node)
|
|
41
|
-
};
|
|
42
|
-
return node;
|
|
54
|
+
getKey(data) {
|
|
55
|
+
return data[this.keyField];
|
|
43
56
|
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* TreeNode 类 - 树节点,包含数据和方法
|
|
60
|
+
* @template T 节点数据的类型
|
|
61
|
+
*
|
|
62
|
+
* @description
|
|
63
|
+
* TreeNode 是树结构的基本单元,每个节点包含:
|
|
64
|
+
* - 节点数据(item)
|
|
65
|
+
* - 父节点引用(parent)
|
|
66
|
+
* - 子节点列表(children)
|
|
67
|
+
* - 展开状态(expand)
|
|
68
|
+
* - 加载状态(loading)
|
|
69
|
+
*
|
|
70
|
+
* 节点提供了丰富的操作方法,可以直接在节点上进行增删改查操作。
|
|
71
|
+
*/
|
|
72
|
+
export class TreeNode {
|
|
73
|
+
/**
|
|
74
|
+
* 节点数据(私有,只读)
|
|
75
|
+
* @private
|
|
76
|
+
*/
|
|
77
|
+
_item;
|
|
78
|
+
/**
|
|
79
|
+
* 节点层级(私有)
|
|
80
|
+
* @private
|
|
81
|
+
*/
|
|
82
|
+
_level;
|
|
83
|
+
/**
|
|
84
|
+
* 是否展开(显示子节点)
|
|
85
|
+
*/
|
|
86
|
+
expand = false;
|
|
44
87
|
/**
|
|
45
|
-
*
|
|
88
|
+
* 是否正在加载(用于懒加载)
|
|
46
89
|
*/
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
90
|
+
loading = false;
|
|
91
|
+
/**
|
|
92
|
+
* 父节点(只读)
|
|
93
|
+
*/
|
|
94
|
+
parent = null;
|
|
95
|
+
/**
|
|
96
|
+
* 子节点数组(私有)
|
|
97
|
+
* @private
|
|
98
|
+
*/
|
|
99
|
+
_children = null;
|
|
100
|
+
/**
|
|
101
|
+
* 创建树节点
|
|
102
|
+
* @param item 节点数据
|
|
103
|
+
* @param parent 父节点(可选)
|
|
104
|
+
* @param children 子节点列表(可选)
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* // 创建根节点
|
|
108
|
+
* const rootNode = new TreeNode({ id: 1, name: "根节点" });
|
|
109
|
+
*
|
|
110
|
+
* // 创建子节点
|
|
111
|
+
* const childNode = new TreeNode({ id: 2, name: "子节点" }, rootNode);
|
|
112
|
+
*/
|
|
113
|
+
constructor(item, parent = null, children = null) {
|
|
114
|
+
this._item = item;
|
|
115
|
+
this._level = parent ? parent._level + 1 : 0;
|
|
116
|
+
this.parent = parent;
|
|
117
|
+
this._children = children;
|
|
118
|
+
this.expand = false;
|
|
119
|
+
// 如果有父节点,将自己添加到父节点的 children 中
|
|
120
|
+
if (parent) {
|
|
121
|
+
if (!parent._children) {
|
|
122
|
+
parent._children = [];
|
|
123
|
+
}
|
|
124
|
+
parent._children.push(this);
|
|
52
125
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* 获取节点层级
|
|
129
|
+
* @returns 层级值(根节点为 0)
|
|
130
|
+
*/
|
|
131
|
+
get level() {
|
|
132
|
+
return this._level;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* 获取子节点列表(只读)
|
|
136
|
+
* @returns 子节点数组的浅拷贝,如果没有子节点返回 null
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* const children = node.children;
|
|
140
|
+
* if (children) {
|
|
141
|
+
* children.forEach(child => console.log(child.item));
|
|
142
|
+
* }
|
|
143
|
+
*/
|
|
144
|
+
get children() {
|
|
145
|
+
return this._children ? [...this._children] : null;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* 添加子节点
|
|
149
|
+
* @param childItem 子节点数据
|
|
150
|
+
* @returns 新创建的子节点
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* const childNode = parentNode.append({ id: 1, name: "子节点" });
|
|
154
|
+
*/
|
|
155
|
+
append(childItem) {
|
|
156
|
+
return new TreeNode(childItem, this);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* 从父节点中分离(删除当前节点)
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* node.detach();
|
|
163
|
+
*/
|
|
164
|
+
detach() {
|
|
165
|
+
if (!this.parent) {
|
|
166
|
+
console.warn('TreeNode is not attached to a tree, cannot detach');
|
|
167
|
+
return;
|
|
59
168
|
}
|
|
60
|
-
|
|
61
|
-
this.nodeMap.set(childItem[this.keyField], childNode);
|
|
62
|
-
this.touch();
|
|
169
|
+
this.parent.removeNode(this);
|
|
63
170
|
}
|
|
64
171
|
/**
|
|
65
|
-
*
|
|
172
|
+
* 删除指定的子节点
|
|
173
|
+
* @param node 要删除的子节点
|
|
174
|
+
* @private
|
|
66
175
|
*/
|
|
67
176
|
removeNode(node) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
177
|
+
if (this._children) {
|
|
178
|
+
let idx = this._children.indexOf(node);
|
|
179
|
+
if (idx >= 0) {
|
|
180
|
+
this._children.splice(idx, 1);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
console.warn(' The removed node has not been attached to this.');
|
|
75
184
|
}
|
|
76
185
|
}
|
|
77
186
|
else {
|
|
78
|
-
|
|
79
|
-
this._nodes = this._nodes.filter(el => el.item[this.keyField] != idKey);
|
|
187
|
+
console.warn(' The removed node has not been attached to this.');
|
|
80
188
|
}
|
|
81
|
-
this.touch();
|
|
82
189
|
}
|
|
83
190
|
/**
|
|
84
|
-
*
|
|
191
|
+
* 移动到另一个父节点下
|
|
192
|
+
* @param newParent 新的父节点
|
|
193
|
+
* @returns 新创建的节点(注意:返回的是新节点,不是原节点)
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* node.moveTo(newParentNode);
|
|
85
197
|
*/
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
// 如果排序字段改变了,需要重新排序
|
|
89
|
-
const parentKey = node.item[this.parentKeyField];
|
|
90
|
-
const parentNode = this.nodeMap.get(parentKey);
|
|
91
|
-
if (parentNode && parentNode.children && parentNode.children.length > 0) {
|
|
92
|
-
parentNode.children = parentNode.children.sort((n1, n2) => {
|
|
93
|
-
return this.compareFun?.(n1.item, n2.item);
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
this._nodes.sort((n1, n2) => {
|
|
98
|
-
return this.compareFun?.(n1.item, n2.item);
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
this.touch();
|
|
198
|
+
moveTo(newParent) {
|
|
199
|
+
return new TreeNode(this._item, newParent, this._children);
|
|
102
200
|
}
|
|
103
201
|
/**
|
|
104
|
-
*
|
|
202
|
+
* 替换当前节点的数据
|
|
203
|
+
* @param newItem 新的数据对象
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* node.replace({ id: 1, name: "新名称", ...otherFields });
|
|
105
207
|
*/
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const currentParentKey = node.item[this.parentKeyField];
|
|
109
|
-
const currentParent = this.nodeMap.get(currentParentKey);
|
|
110
|
-
if (!newParent || !currentParent) {
|
|
111
|
-
console.warn('Cannot move node: parent not found');
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
// 从当前父节点移除
|
|
115
|
-
if (currentParent.children) {
|
|
116
|
-
currentParent.children = currentParent.children.filter(el => el.item[this.keyField] != node.item[this.keyField]);
|
|
117
|
-
}
|
|
118
|
-
// 如果新父节点还没有 children,初始化数组
|
|
119
|
-
if (newParent.children == null) {
|
|
120
|
-
newParent.children = [];
|
|
121
|
-
}
|
|
122
|
-
// 添加到新父节点
|
|
123
|
-
newParent.children = [...newParent.children, node];
|
|
124
|
-
if (this.compareFun) {
|
|
125
|
-
newParent.children = newParent.children.sort((n1, n2) => {
|
|
126
|
-
return this.compareFun(n1.item, n2.item);
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
// 更新节点的 parentKeyField
|
|
130
|
-
node.item[this.parentKeyField] = newParentId;
|
|
131
|
-
this.touch();
|
|
208
|
+
replace(newItem) {
|
|
209
|
+
this._item = newItem;
|
|
132
210
|
}
|
|
133
211
|
/**
|
|
134
|
-
*
|
|
212
|
+
* 获取节点数据
|
|
213
|
+
* @returns 节点数据对象
|
|
135
214
|
*/
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return;
|
|
139
|
-
const childNode = parentNode.children.find(child => child.item[this.keyField] == childId);
|
|
140
|
-
if (!childNode)
|
|
141
|
-
return;
|
|
142
|
-
// 从 children 数组中移除
|
|
143
|
-
parentNode.children = parentNode.children.filter(child => child.item[this.keyField] != childId);
|
|
144
|
-
// 从 nodeMap 中删除
|
|
145
|
-
this.nodeMap.delete(childId);
|
|
146
|
-
this.touch();
|
|
215
|
+
get item() {
|
|
216
|
+
return this._item;
|
|
147
217
|
}
|
|
148
218
|
/**
|
|
149
|
-
*
|
|
219
|
+
* 删除所有子节点
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* node.removeChildren();
|
|
150
223
|
*/
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
224
|
+
removeChildren() {
|
|
225
|
+
this._children = [];
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* @internal 仅供 TreeNodes 内部使用
|
|
229
|
+
* 设置父节点,并将自己添加到父节点的 children 中
|
|
230
|
+
* @param parent 新的父节点
|
|
231
|
+
*
|
|
232
|
+
* @description
|
|
233
|
+
* 此方法会:
|
|
234
|
+
* 1. 从原父节点的 children 中移除自己
|
|
235
|
+
* 2. 更新父节点引用
|
|
236
|
+
* 3. 重新计算层级
|
|
237
|
+
* 4. 将自己添加到新父节点的 children 中
|
|
238
|
+
*/
|
|
239
|
+
_setParent(parent) {
|
|
240
|
+
// 从原父节点的 children 中移除自己
|
|
241
|
+
const oldParent = this.parent;
|
|
242
|
+
if (oldParent && oldParent._children) {
|
|
243
|
+
const index = oldParent._children.indexOf(this);
|
|
244
|
+
if (index >= 0) {
|
|
245
|
+
oldParent._children.splice(index, 1);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// 设置新父节点
|
|
249
|
+
this.parent = parent;
|
|
250
|
+
this._level = parent ? parent._level + 1 : 0;
|
|
251
|
+
// 将自己添加到新父节点的 children 中
|
|
252
|
+
if (parent) {
|
|
253
|
+
if (!parent._children) {
|
|
254
|
+
parent._children = [];
|
|
255
|
+
}
|
|
256
|
+
parent._children.push(this);
|
|
158
257
|
}
|
|
159
|
-
// 清空 children 数组
|
|
160
|
-
parentNode.children = [];
|
|
161
|
-
this.touch();
|
|
162
258
|
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* TreeNodes 类 - 树节点管理器
|
|
262
|
+
* @template T 节点数据的类型
|
|
263
|
+
*
|
|
264
|
+
* @description
|
|
265
|
+
* TreeNodes 负责管理树结构的数据,包括:
|
|
266
|
+
* - 树的构建和初始化
|
|
267
|
+
* - 节点的映射和查找
|
|
268
|
+
* - 版本管理(用于响应式更新)
|
|
269
|
+
* - 层级展开控制
|
|
270
|
+
*
|
|
271
|
+
* @example
|
|
272
|
+
* interface MyData {
|
|
273
|
+
* id: number;
|
|
274
|
+
* name: string;
|
|
275
|
+
* parentId: number | null;
|
|
276
|
+
* }
|
|
277
|
+
*
|
|
278
|
+
* const treeNodes = new TreeNodes<MyData>({
|
|
279
|
+
* keyField: 'id',
|
|
280
|
+
* textField: 'name',
|
|
281
|
+
* parentKeyField: 'parentId',
|
|
282
|
+
* checkIsRoot: (item) => item.parentId === null,
|
|
283
|
+
* checkIsDirectory: (node) => node.children !== null,
|
|
284
|
+
* expendDepth: 2
|
|
285
|
+
* });
|
|
286
|
+
*
|
|
287
|
+
* treeNodes.setData([
|
|
288
|
+
* { id: 1, name: "根节点", parentId: null },
|
|
289
|
+
* { id: 2, name: "子节点1", parentId: 1 },
|
|
290
|
+
* { id: 3, name: "子节点2", parentId: 1 }
|
|
291
|
+
* ]);
|
|
292
|
+
*/
|
|
293
|
+
export default class TreeNodes {
|
|
294
|
+
checkIsRoot;
|
|
295
|
+
keyField;
|
|
296
|
+
parentKeyField;
|
|
297
|
+
textField;
|
|
298
|
+
checkIsDirectory;
|
|
299
|
+
nodeMap;
|
|
300
|
+
compareFun;
|
|
301
|
+
expendDepth;
|
|
302
|
+
_nodes = [];
|
|
303
|
+
_version = 0;
|
|
304
|
+
/**
|
|
305
|
+
* 创建 TreeNodes 实例
|
|
306
|
+
* @param options 配置选项
|
|
307
|
+
*/
|
|
308
|
+
constructor(options) {
|
|
309
|
+
this.checkIsRoot = options.checkIsRoot;
|
|
310
|
+
this.compareFun = options.compareFun;
|
|
311
|
+
this.keyField = options.keyField ?? 'id';
|
|
312
|
+
this.textField = options.textField ?? 'text';
|
|
313
|
+
this.parentKeyField = options.parentKeyField ?? 'parentId';
|
|
314
|
+
this.nodeMap = new Map();
|
|
315
|
+
this.expendDepth = options.expendDepth ?? 1;
|
|
316
|
+
this.checkIsDirectory = options.checkIsDirectory;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* 设置树数据
|
|
320
|
+
* @param list 扁平化的节点数据数组
|
|
321
|
+
*
|
|
322
|
+
* @description
|
|
323
|
+
* 此方法会:
|
|
324
|
+
* 1. 清空现有树结构
|
|
325
|
+
* 2. 创建所有节点
|
|
326
|
+
* 3. 根据 parentKeyField 建立父子关系
|
|
327
|
+
* 4. 应用展开深度设置
|
|
328
|
+
* 5. 触发版本更新
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
* treeNodes.setData([
|
|
332
|
+
* { id: 1, name: "根节点", parentId: null },
|
|
333
|
+
* { id: 2, name: "子节点1", parentId: 1 },
|
|
334
|
+
* { id: 3, name: "子节点2", parentId: 1 }
|
|
335
|
+
* ]);
|
|
336
|
+
*/
|
|
163
337
|
setData(list) {
|
|
164
338
|
this.nodeMap = new Map();
|
|
165
339
|
this._nodes = [];
|
|
166
|
-
//
|
|
340
|
+
// 第一遍:创建所有节点(不设置父子关系)
|
|
167
341
|
for (const item of list) {
|
|
168
|
-
const node = this.createNodeWithMethods(item);
|
|
169
342
|
const key = item[this.keyField];
|
|
343
|
+
const node = new TreeNode(item); // 创建节点时不设置 parent
|
|
170
344
|
this.nodeMap.set(key, node);
|
|
171
345
|
}
|
|
346
|
+
// 第二遍:建立父子关系
|
|
172
347
|
for (const item of list) {
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
348
|
+
const key = item[this.keyField];
|
|
349
|
+
const node = this.nodeMap.get(key);
|
|
350
|
+
if (this.checkIsRoot(item)) {
|
|
351
|
+
// 是根节点
|
|
352
|
+
this._nodes.push(node);
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
// 不是根节点,找到父节点并建立关系
|
|
356
|
+
const parentKey = item[this.parentKeyField];
|
|
357
|
+
const parentNode = this.nodeMap.get(parentKey);
|
|
358
|
+
if (parentNode) {
|
|
359
|
+
// 使用 _setParent 方法建立父子关系
|
|
360
|
+
node._setParent(parentNode);
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
console.warn(`Parent node ${parentKey} not found for item ${key}, treating as root node`);
|
|
364
|
+
this._nodes.push(node);
|
|
365
|
+
}
|
|
176
366
|
}
|
|
177
367
|
}
|
|
178
|
-
|
|
179
|
-
|
|
368
|
+
// 应用展开深度设置
|
|
369
|
+
if (this.expendDepth > 0) {
|
|
370
|
+
this.setExpandForDepth(this._nodes, 0);
|
|
180
371
|
}
|
|
181
|
-
|
|
372
|
+
// 触发版本更新
|
|
373
|
+
this._version++;
|
|
182
374
|
}
|
|
183
375
|
/**
|
|
184
376
|
* 获取节点
|
|
@@ -203,99 +395,77 @@ export class CommonTreeNodes {
|
|
|
203
395
|
setExpandForDepth(nodes, currentLevel) {
|
|
204
396
|
for (const node of nodes) {
|
|
205
397
|
node.expand = currentLevel < this.expendDepth;
|
|
206
|
-
if (node.
|
|
207
|
-
|
|
208
|
-
}
|
|
398
|
+
// if (node.getInternalChildren().length > 0) {
|
|
399
|
+
// this.setExpandForDepth(node.getInternalChildren(), currentLevel + 1);
|
|
400
|
+
// }
|
|
209
401
|
}
|
|
210
402
|
}
|
|
211
403
|
/**
|
|
212
|
-
*
|
|
213
|
-
* @param node
|
|
214
|
-
* @param doSort
|
|
215
|
-
* @protected
|
|
404
|
+
* 获取展开的展示列表
|
|
216
405
|
*/
|
|
217
|
-
|
|
218
|
-
let
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const parentNode = this.nodeMap.get(parentKey);
|
|
228
|
-
if (parentNode) {
|
|
229
|
-
parentNode.expand = true;
|
|
230
|
-
parentNode.children = [...(parentNode.children ?? []), node];
|
|
231
|
-
if (doSort && this.compareFun) {
|
|
232
|
-
parentNode.children = parentNode.children.sort((n1, n2) => {
|
|
233
|
-
return this.compareFun(n1.item, n2.item);
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
else {
|
|
238
|
-
console.warn('Ignore the isolate item:', item);
|
|
406
|
+
getHierarchyList() {
|
|
407
|
+
let arr = [];
|
|
408
|
+
this.addExpandNodesToList(this.nodes, arr);
|
|
409
|
+
return arr;
|
|
410
|
+
}
|
|
411
|
+
addExpandNodesToList(nodes, list) {
|
|
412
|
+
for (let node of nodes) {
|
|
413
|
+
list.push(node);
|
|
414
|
+
if (node.expand) {
|
|
415
|
+
this.addExpandNodesToList(node.children ?? [], list);
|
|
239
416
|
}
|
|
240
417
|
}
|
|
241
418
|
}
|
|
242
|
-
}
|
|
243
|
-
export default class TreeNodes extends CommonTreeNodes {
|
|
244
419
|
/**
|
|
245
|
-
*
|
|
420
|
+
* 不检测匹配情况,在指定的父节点下添加子节点
|
|
246
421
|
*/
|
|
247
|
-
|
|
248
|
-
|
|
422
|
+
batchAttachToParent(parent, list) {
|
|
423
|
+
let nodes = [];
|
|
424
|
+
for (let item of list) {
|
|
425
|
+
nodes.push(new TreeNode(item, parent));
|
|
426
|
+
}
|
|
427
|
+
return nodes;
|
|
249
428
|
}
|
|
250
429
|
/**
|
|
251
430
|
* 增加一个新节点(便捷方法,会自动根据 parentKeyField 找到父节点)
|
|
252
431
|
* @param item 要添加的节点数据
|
|
253
432
|
*/
|
|
254
433
|
append(item) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
434
|
+
if (parent) {
|
|
435
|
+
if (this.checkIsRoot(item)) {
|
|
436
|
+
let node = new TreeNode(item);
|
|
437
|
+
this._nodes.push(node);
|
|
438
|
+
this._version++;
|
|
439
|
+
return node;
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
throw new Error(`the entity is not a root data`);
|
|
443
|
+
}
|
|
260
444
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
extractDirectories(exclusiveData) {
|
|
268
|
-
const getNodes = (nodes, item) => {
|
|
269
|
-
let list = [];
|
|
270
|
-
for (let node of nodes) {
|
|
271
|
-
if (node.item != item && this.checkIsDirectory?.(node)) {
|
|
272
|
-
list.push({
|
|
273
|
-
item: node.item,
|
|
274
|
-
expand: true,
|
|
275
|
-
children: getNodes(node.children ?? [], item)
|
|
276
|
-
});
|
|
277
|
-
}
|
|
445
|
+
else {
|
|
446
|
+
let parent = this.findParent(this.nodes, item);
|
|
447
|
+
if (!parent) {
|
|
448
|
+
let node = new TreeNode(item, parent);
|
|
449
|
+
this._version++;
|
|
450
|
+
return node;
|
|
278
451
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
452
|
+
else {
|
|
453
|
+
throw new Error(`cannot find the parent.`);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
282
456
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
result.push(node);
|
|
293
|
-
if (node.expand && node.children) {
|
|
294
|
-
traverse(node.children);
|
|
457
|
+
findParent(nodes, item) {
|
|
458
|
+
let found = null;
|
|
459
|
+
for (const node of nodes) {
|
|
460
|
+
if (!found) {
|
|
461
|
+
if (node.item[this.keyField] == item[this.parentKeyField]) {
|
|
462
|
+
found = node;
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
found = node.children && node.children.length > 0 ? this.findParent(node.children, item) : null;
|
|
295
466
|
}
|
|
296
467
|
}
|
|
297
468
|
}
|
|
298
|
-
|
|
299
|
-
return result;
|
|
469
|
+
return found;
|
|
300
470
|
}
|
|
301
471
|
}
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import TreeNodes from "./TreeNodes";
|
|
2
|
-
import type {
|
|
3
|
-
import { CommonTreeNodes } from "./TreeNodes";
|
|
2
|
+
import type { ITreeNode } from "./TreeNodes";
|
|
4
3
|
import type { CheckIsRoot, CompareFun, GetText, CheckIsDirectory, TreeNodeOptions } from "./TreeNodes";
|
|
5
4
|
import { compareNumber } from "./TreeNodes";
|
|
6
5
|
export default TreeNodes;
|
|
7
|
-
export {
|
|
8
|
-
export type {
|
|
6
|
+
export { compareNumber };
|
|
7
|
+
export type { ITreeNode };
|
|
9
8
|
export type { CheckIsRoot, CompareFun, GetText, CheckIsDirectory, TreeNodeOptions };
|
package/dist/lib/index.js
CHANGED
package/dist/nav-menu/Menus.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import TreeNodes from "../lib/TreeNodes";
|
|
2
2
|
import type MenuItem from "./MenuItem";
|
|
3
|
-
export default class Menus extends
|
|
3
|
+
export default class Menus extends TreeNodes<MenuItem> {
|
|
4
4
|
/**
|
|
5
5
|
* 删除所有没有子节点的目录类型节点
|
|
6
6
|
*/
|