sculp-js 1.13.4 → 1.14.0

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.
Files changed (62) hide show
  1. package/README.md +3 -1
  2. package/dist/cjs/_virtual/_commonjsHelpers.js +3 -3
  3. package/dist/cjs/array.js +36 -46
  4. package/dist/cjs/async.js +41 -43
  5. package/dist/cjs/base64.js +77 -66
  6. package/dist/cjs/clipboard.js +54 -53
  7. package/dist/cjs/cloneDeep.js +90 -91
  8. package/dist/cjs/cookie.js +27 -30
  9. package/dist/cjs/date.js +101 -98
  10. package/dist/cjs/dom.js +114 -121
  11. package/dist/cjs/download.js +77 -78
  12. package/dist/cjs/easing.js +29 -32
  13. package/dist/cjs/file.js +147 -152
  14. package/dist/cjs/func.js +64 -78
  15. package/dist/cjs/index.js +3 -3
  16. package/dist/cjs/math.js +32 -38
  17. package/dist/cjs/node_modules/bezier-easing/src/index.js +35 -23
  18. package/dist/cjs/number.js +56 -61
  19. package/dist/cjs/object.js +112 -126
  20. package/dist/cjs/path.js +39 -43
  21. package/dist/cjs/qs.js +34 -41
  22. package/dist/cjs/random.js +31 -34
  23. package/dist/cjs/string.js +62 -63
  24. package/dist/cjs/tooltip.js +66 -69
  25. package/dist/cjs/tree.js +329 -258
  26. package/dist/cjs/type.js +42 -46
  27. package/dist/cjs/unique.js +39 -42
  28. package/dist/cjs/url.js +47 -48
  29. package/dist/cjs/validator.js +38 -38
  30. package/dist/cjs/variable.js +27 -21
  31. package/dist/cjs/watermark.js +78 -67
  32. package/dist/esm/array.js +36 -46
  33. package/dist/esm/async.js +41 -43
  34. package/dist/esm/base64.js +77 -66
  35. package/dist/esm/clipboard.js +55 -54
  36. package/dist/esm/cloneDeep.js +90 -91
  37. package/dist/esm/cookie.js +27 -30
  38. package/dist/esm/date.js +101 -98
  39. package/dist/esm/dom.js +114 -121
  40. package/dist/esm/download.js +78 -79
  41. package/dist/esm/easing.js +29 -32
  42. package/dist/esm/file.js +147 -152
  43. package/dist/esm/func.js +64 -78
  44. package/dist/esm/index.js +106 -9
  45. package/dist/esm/math.js +32 -38
  46. package/dist/esm/number.js +57 -62
  47. package/dist/esm/object.js +124 -127
  48. package/dist/esm/path.js +39 -43
  49. package/dist/esm/qs.js +34 -41
  50. package/dist/esm/random.js +31 -34
  51. package/dist/esm/string.js +74 -64
  52. package/dist/esm/tooltip.js +66 -69
  53. package/dist/esm/tree.js +329 -260
  54. package/dist/esm/type.js +68 -47
  55. package/dist/esm/unique.js +39 -42
  56. package/dist/esm/url.js +47 -48
  57. package/dist/esm/validator.js +56 -39
  58. package/dist/esm/variable.js +27 -21
  59. package/dist/esm/watermark.js +79 -68
  60. package/dist/types/tree.d.ts +36 -0
  61. package/dist/umd/index.min.js +2 -2
  62. package/package.json +11 -7
package/dist/esm/tree.js CHANGED
@@ -1,18 +1,18 @@
1
1
  /*!
2
- * sculp-js v1.13.4
2
+ * sculp-js v1.14.0
3
3
  * (c) 2023-present chandq
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
7
7
  import { objectOmit } from './object.js';
8
- import { isObject, objectHas, isEmpty, isNodeList } from './type.js';
8
+ import { isObject, objectHas, isNodeList } from './type.js';
9
9
 
10
10
  const defaultFieldOptions = { keyField: 'key', childField: 'children', pidField: 'pid' };
11
11
  const defaultSearchTreeOptions = {
12
- childField: 'children',
13
- nameField: 'name',
14
- removeEmptyChild: false,
15
- ignoreCase: true
12
+ childField: 'children',
13
+ nameField: 'name',
14
+ removeEmptyChild: false,
15
+ ignoreCase: true
16
16
  };
17
17
  /**
18
18
  * 树遍历函数(支持continue和break操作), 可用于遍历Array和NodeList类型的数据
@@ -26,106 +26,177 @@ const defaultSearchTreeOptions = {
26
26
  }
27
27
  * @returns {*}
28
28
  */
29
- function forEachDeep(tree, iterator, options = {
29
+ function forEachDeep(
30
+ tree,
31
+ iterator,
32
+ options = {
30
33
  childField: 'children',
31
34
  reverse: false,
32
35
  breadthFirst: false,
33
36
  isDomNode: false
34
- }) {
35
- const { childField = 'children', reverse = false, breadthFirst = false, isDomNode = false } = isObject(options) ? options : {};
36
- let isBreak = false;
37
- const queue = [];
38
- const reverseWalk = (arr, parent, level = 0) => {
39
- for (let index = arr.length - 1; index >= 0; index--) {
40
- if (isBreak) {
41
- break;
42
- }
43
- const item = arr[index];
44
- // 广度优先
45
- if (breadthFirst) {
46
- queue.push({ item, index, array: arr, tree, parent, level });
47
- }
48
- else {
49
- const re = iterator(item, index, arr, tree, parent, level);
50
- if (re === false) {
51
- isBreak = true;
52
- break;
53
- }
54
- else if (re === true) {
55
- continue;
56
- }
57
- if (item && (isDomNode ? isNodeList(item[childField]) : Array.isArray(item[childField]))) {
58
- reverseWalk(item[childField], item, level + 1);
59
- }
60
- }
37
+ }
38
+ ) {
39
+ const {
40
+ childField = 'children',
41
+ reverse = false,
42
+ breadthFirst = false,
43
+ isDomNode = false
44
+ } = isObject(options) ? options : {};
45
+ let isBreak = false;
46
+ const queue = [];
47
+ const reverseWalk = (arr, parent, level = 0) => {
48
+ for (let index = arr.length - 1; index >= 0; index--) {
49
+ if (isBreak) {
50
+ break;
51
+ }
52
+ const item = arr[index];
53
+ // 广度优先
54
+ if (breadthFirst) {
55
+ queue.push({ item, index, array: arr, tree, parent, level });
56
+ } else {
57
+ const re = iterator(item, index, arr, tree, parent, level);
58
+ if (re === false) {
59
+ isBreak = true;
60
+ break;
61
+ } else if (re === true) {
62
+ continue;
61
63
  }
62
- if (breadthFirst) {
63
- // Process queue
64
- while (queue.length > 0 && !isBreak) {
65
- const current = queue.shift();
66
- const { item, index, array, tree, parent, level } = current;
67
- const re = iterator(item, index, array, tree, parent, level);
68
- if (re === false) {
69
- isBreak = true;
70
- break;
71
- }
72
- else if (re === true) {
73
- continue;
74
- }
75
- if (item && (isDomNode ? isNodeList(item[childField]) : Array.isArray(item[childField]))) {
76
- reverseWalk(item[childField], item, level + 1);
77
- }
78
- }
64
+ if (item && (isDomNode ? isNodeList(item[childField]) : Array.isArray(item[childField]))) {
65
+ reverseWalk(item[childField], item, level + 1);
79
66
  }
80
- };
81
- const walk = (arr, parent, level = 0) => {
82
- for (let index = 0, len = arr.length; index < len; index++) {
83
- if (isBreak) {
84
- break;
85
- }
86
- const item = arr[index];
87
- if (breadthFirst) {
88
- // 广度优先
89
- queue.push({ item, index: index, array: arr, tree, parent, level });
90
- }
91
- else {
92
- // 深度优先
93
- const re = iterator(item, index, arr, tree, parent, level);
94
- if (re === false) {
95
- isBreak = true;
96
- break;
97
- }
98
- else if (re === true) {
99
- continue;
100
- }
101
- if (item && (isDomNode ? isNodeList(item[childField]) : Array.isArray(item[childField]))) {
102
- walk(item[childField], item, level + 1);
103
- }
104
- }
67
+ }
68
+ }
69
+ if (breadthFirst) {
70
+ // Process queue
71
+ while (queue.length > 0 && !isBreak) {
72
+ const current = queue.shift();
73
+ const { item, index, array, tree, parent, level } = current;
74
+ const re = iterator(item, index, array, tree, parent, level);
75
+ if (re === false) {
76
+ isBreak = true;
77
+ break;
78
+ } else if (re === true) {
79
+ continue;
105
80
  }
106
- if (breadthFirst) {
107
- while (queue.length > 0 && !isBreak) {
108
- const current = queue.shift();
109
- if (!current)
110
- break;
111
- const { item, index, array, tree, parent, level } = current;
112
- const re = iterator(item, index, array, tree, parent, level);
113
- if (re === false) {
114
- isBreak = true;
115
- break;
116
- }
117
- else if (re === true) {
118
- continue;
119
- }
120
- if (item && (isDomNode ? isNodeList(item[childField]) : Array.isArray(item[childField]))) {
121
- walk(item[childField], item, level + 1);
122
- }
123
- }
81
+ if (item && (isDomNode ? isNodeList(item[childField]) : Array.isArray(item[childField]))) {
82
+ reverseWalk(item[childField], item, level + 1);
124
83
  }
125
- };
126
- reverse ? reverseWalk(tree, null, 0) : walk(tree, null, 0);
127
- // @ts-ignore
128
- tree = null;
84
+ }
85
+ }
86
+ };
87
+ const walk = (arr, parent, level = 0) => {
88
+ for (let index = 0, len = arr.length; index < len; index++) {
89
+ if (isBreak) {
90
+ break;
91
+ }
92
+ const item = arr[index];
93
+ if (breadthFirst) {
94
+ // 广度优先
95
+ queue.push({ item, index: index, array: arr, tree, parent, level });
96
+ } else {
97
+ // 深度优先
98
+ const re = iterator(item, index, arr, tree, parent, level);
99
+ if (re === false) {
100
+ isBreak = true;
101
+ break;
102
+ } else if (re === true) {
103
+ continue;
104
+ }
105
+ if (item && (isDomNode ? isNodeList(item[childField]) : Array.isArray(item[childField]))) {
106
+ walk(item[childField], item, level + 1);
107
+ }
108
+ }
109
+ }
110
+ if (breadthFirst) {
111
+ while (queue.length > 0 && !isBreak) {
112
+ const current = queue.shift();
113
+ if (!current) break;
114
+ const { item, index, array, tree, parent, level } = current;
115
+ const re = iterator(item, index, array, tree, parent, level);
116
+ if (re === false) {
117
+ isBreak = true;
118
+ break;
119
+ } else if (re === true) {
120
+ continue;
121
+ }
122
+ if (item && (isDomNode ? isNodeList(item[childField]) : Array.isArray(item[childField]))) {
123
+ walk(item[childField], item, level + 1);
124
+ }
125
+ }
126
+ }
127
+ };
128
+ reverse ? reverseWalk(tree, null, 0) : walk(tree, null, 0);
129
+ // @ts-ignore
130
+ tree = null;
131
+ }
132
+ /**
133
+ * 树查找函数, 可用于查找Array和NodeList类型的数据
134
+ * @param {ArrayLike<V>} tree 树形数据
135
+ * @param {Function} predicate 断言函数
136
+ * @param {options} options 支持定制子元素名称、反向遍历、广度优先遍历,默认{
137
+ childField: 'children',
138
+ reverse: false,
139
+ breadthFirst: false,
140
+ isDomNode: false,
141
+ }
142
+ * @returns {V|null}
143
+ */
144
+ function findDeep(
145
+ tree,
146
+ predicate,
147
+ options = {
148
+ childField: 'children',
149
+ reverse: false,
150
+ breadthFirst: false,
151
+ isDomNode: false
152
+ }
153
+ ) {
154
+ let result = null;
155
+ forEachDeep(
156
+ tree,
157
+ (...args) => {
158
+ if (predicate(...args)) {
159
+ result = args[0];
160
+ return false;
161
+ }
162
+ },
163
+ options
164
+ );
165
+ return result;
166
+ }
167
+ /**
168
+ * 树过滤函数, 可用于过滤Array和NodeList类型的数据
169
+ * @param {ArrayLike<V>} tree 树形数据
170
+ * @param {Function} predicate 断言函数
171
+ * @param {options} options 支持定制子元素名称、反向遍历、广度优先遍历,默认{
172
+ childField: 'children',
173
+ reverse: false,
174
+ breadthFirst: false,
175
+ isDomNode: false,
176
+ }
177
+ * @returns {V|null}
178
+ */
179
+ function filterDeep(
180
+ tree,
181
+ predicate,
182
+ options = {
183
+ childField: 'children',
184
+ reverse: false,
185
+ breadthFirst: false,
186
+ isDomNode: false
187
+ }
188
+ ) {
189
+ const result = [];
190
+ forEachDeep(
191
+ tree,
192
+ (...args) => {
193
+ if (predicate(...args)) {
194
+ result.push(args[0]);
195
+ }
196
+ },
197
+ options
198
+ );
199
+ return result;
129
200
  }
130
201
  /**
131
202
  * 创建一个新数组, 深度优先遍历的Map函数(支持continue和break操作), 可用于insert tree item 和 remove tree item
@@ -139,69 +210,68 @@ function forEachDeep(tree, iterator, options = {
139
210
  }
140
211
  * @returns {any[]} 新的一棵树
141
212
  */
142
- function mapDeep(tree, iterator, options = {
213
+ function mapDeep(
214
+ tree,
215
+ iterator,
216
+ options = {
143
217
  childField: 'children',
144
218
  reverse: false
145
- }) {
146
- const { childField = 'children', reverse = false } = isObject(options) ? options : {};
147
- let isBreak = false;
148
- const newTree = [];
149
- const walk = (arr, parent, newTree, level = 0) => {
150
- if (reverse) {
151
- for (let i = arr.length - 1; i >= 0; i--) {
152
- if (isBreak) {
153
- break;
154
- }
155
- const item = arr[i];
156
- const re = iterator(item, i, arr, tree, parent, level);
157
- if (re === false) {
158
- isBreak = true;
159
- break;
160
- }
161
- else if (re === true) {
162
- continue;
163
- }
164
- newTree.push(objectOmit(re, [childField]));
165
- if (item && Array.isArray(item[childField])) {
166
- newTree[newTree.length - 1][childField] = [];
167
- walk(item[childField], item, newTree[newTree.length - 1][childField], level + 1);
168
- }
169
- else {
170
- // children非有效数组时,移除该属性字段
171
- delete re[childField];
172
- }
173
- }
219
+ }
220
+ ) {
221
+ const { childField = 'children', reverse = false } = isObject(options) ? options : {};
222
+ let isBreak = false;
223
+ const newTree = [];
224
+ const walk = (arr, parent, newTree, level = 0) => {
225
+ if (reverse) {
226
+ for (let i = arr.length - 1; i >= 0; i--) {
227
+ if (isBreak) {
228
+ break;
174
229
  }
175
- else {
176
- for (let i = 0; i < arr.length; i++) {
177
- if (isBreak) {
178
- break;
179
- }
180
- const item = arr[i];
181
- const re = iterator(item, i, arr, tree, parent, level);
182
- if (re === false) {
183
- isBreak = true;
184
- break;
185
- }
186
- else if (re === true) {
187
- continue;
188
- }
189
- newTree.push(objectOmit(re, [childField]));
190
- if (item && Array.isArray(item[childField])) {
191
- newTree[newTree.length - 1][childField] = [];
192
- walk(item[childField], item, newTree[newTree.length - 1][childField], level + 1);
193
- }
194
- else {
195
- // children非有效数组时,移除该属性字段
196
- delete re[childField];
197
- }
198
- }
230
+ const item = arr[i];
231
+ const re = iterator(item, i, arr, tree, parent, level);
232
+ if (re === false) {
233
+ isBreak = true;
234
+ break;
235
+ } else if (re === true) {
236
+ continue;
199
237
  }
200
- };
201
- walk(tree, null, newTree);
202
- // @ts-ignore
203
- tree = null;
204
- return newTree;
238
+ newTree.push(objectOmit(re, [childField]));
239
+ if (item && Array.isArray(item[childField])) {
240
+ newTree[newTree.length - 1][childField] = [];
241
+ walk(item[childField], item, newTree[newTree.length - 1][childField], level + 1);
242
+ } else {
243
+ // children非有效数组时,移除该属性字段
244
+ delete re[childField];
245
+ }
246
+ }
247
+ } else {
248
+ for (let i = 0; i < arr.length; i++) {
249
+ if (isBreak) {
250
+ break;
251
+ }
252
+ const item = arr[i];
253
+ const re = iterator(item, i, arr, tree, parent, level);
254
+ if (re === false) {
255
+ isBreak = true;
256
+ break;
257
+ } else if (re === true) {
258
+ continue;
259
+ }
260
+ newTree.push(objectOmit(re, [childField]));
261
+ if (item && Array.isArray(item[childField])) {
262
+ newTree[newTree.length - 1][childField] = [];
263
+ walk(item[childField], item, newTree[newTree.length - 1][childField], level + 1);
264
+ } else {
265
+ // children非有效数组时,移除该属性字段
266
+ delete re[childField];
267
+ }
268
+ }
269
+ }
270
+ };
271
+ walk(tree, null, newTree);
272
+ // @ts-ignore
273
+ tree = null;
274
+ return newTree;
205
275
  }
206
276
  /**
207
277
  * 在树中找到 id 为某个值的节点,并返回上游的所有父级节点
@@ -212,29 +282,30 @@ function mapDeep(tree, iterator, options = {
212
282
  * @returns {[(number | string)[], V[]]} - 由parentId...childId, parentObject-childObject组成的二维数组
213
283
  */
214
284
  function searchTreeById(tree, nodeId, options = { childField: 'children', keyField: 'id' }) {
215
- const { childField = 'children', keyField = 'id' } = isObject(options) ? options : {};
216
- const toFlatArray = (tree, parentId, parent) => {
217
- return tree.reduce((t, _) => {
218
- const child = _[childField];
219
- return [
220
- ...t,
221
- parentId ? { ..._, parentId, parent } : _,
222
- ...(child && child.length ? toFlatArray(child, _[keyField], _) : [])
223
- ];
224
- }, []);
225
- };
226
- const getIds = (flatArray) => {
227
- let child = flatArray.find(_ => _[keyField] === nodeId);
228
- const { parent, parentId, ...other } = child;
229
- let ids = [nodeId], nodes = [other];
230
- while (child && child.parentId) {
231
- ids = [child.parentId, ...ids];
232
- nodes = [child.parent, ...nodes];
233
- child = flatArray.find(_ => _[keyField] === child.parentId); // eslint-disable-line
234
- }
235
- return [ids, nodes];
236
- };
237
- return getIds(toFlatArray(tree));
285
+ const { childField = 'children', keyField = 'id' } = isObject(options) ? options : {};
286
+ const toFlatArray = (tree, parentId, parent) => {
287
+ return tree.reduce((t, _) => {
288
+ const child = _[childField];
289
+ return [
290
+ ...t,
291
+ parentId ? { ..._, parentId, parent } : _,
292
+ ...(child && child.length ? toFlatArray(child, _[keyField], _) : [])
293
+ ];
294
+ }, []);
295
+ };
296
+ const getIds = flatArray => {
297
+ let child = flatArray.find(_ => _[keyField] === nodeId);
298
+ const { parent, parentId, ...other } = child;
299
+ let ids = [nodeId],
300
+ nodes = [other];
301
+ while (child && child.parentId) {
302
+ ids = [child.parentId, ...ids];
303
+ nodes = [child.parent, ...nodes];
304
+ child = flatArray.find(_ => _[keyField] === child.parentId); // eslint-disable-line
305
+ }
306
+ return [ids, nodes];
307
+ };
308
+ return getIds(toFlatArray(tree));
238
309
  }
239
310
  /**
240
311
  * 扁平化数组转换成树
@@ -244,26 +315,25 @@ function searchTreeById(tree, nodeId, options = { childField: 'children', keyFie
244
315
  * @returns {any[]}
245
316
  */
246
317
  function formatTree(list, options = defaultFieldOptions) {
247
- const { keyField = 'key', childField = 'children', pidField = 'pid' } = isObject(options) ? options : {};
248
- const treeArr = [];
249
- const sourceMap = {};
250
- for (let i = 0, len = list.length; i < len; i++) {
251
- const item = list[i];
252
- sourceMap[item[keyField]] = item;
253
- }
254
- for (let i = 0, len = list.length; i < len; i++) {
255
- const item = list[i];
256
- const parent = sourceMap[item[pidField]];
257
- if (parent) {
258
- (parent[childField] || (parent[childField] = [])).push(item);
259
- }
260
- else {
261
- treeArr.push(item);
262
- }
318
+ const { keyField = 'key', childField = 'children', pidField = 'pid' } = isObject(options) ? options : {};
319
+ const treeArr = [];
320
+ const sourceMap = {};
321
+ for (let i = 0, len = list.length; i < len; i++) {
322
+ const item = list[i];
323
+ sourceMap[item[keyField]] = item;
324
+ }
325
+ for (let i = 0, len = list.length; i < len; i++) {
326
+ const item = list[i];
327
+ const parent = sourceMap[item[pidField]];
328
+ if (parent) {
329
+ (parent[childField] || (parent[childField] = [])).push(item);
330
+ } else {
331
+ treeArr.push(item);
263
332
  }
264
- // @ts-ignore
265
- list = null;
266
- return treeArr;
333
+ }
334
+ // @ts-ignore
335
+ list = null;
336
+ return treeArr;
267
337
  }
268
338
  /**
269
339
  * 树形结构转扁平化
@@ -273,25 +343,25 @@ function formatTree(list, options = defaultFieldOptions) {
273
343
  * @returns {any[]}
274
344
  */
275
345
  function flatTree(treeList, options = defaultFieldOptions) {
276
- const { keyField = 'key', childField = 'children', pidField = 'pid' } = isObject(options) ? options : {};
277
- let res = [];
278
- for (let i = 0, len = treeList.length; i < len; i++) {
279
- const node = treeList[i];
280
- const item = {
281
- ...node,
282
- [childField]: [] // 清空子级
283
- };
284
- objectHas(item, childField) && delete item[childField];
285
- res.push(item);
286
- if (node[childField]) {
287
- const children = node[childField].map(item => ({
288
- ...item,
289
- [pidField]: node[keyField] || item.pid // 给子级设置pid
290
- }));
291
- res = res.concat(flatTree(children, options));
292
- }
346
+ const { keyField = 'key', childField = 'children', pidField = 'pid' } = isObject(options) ? options : {};
347
+ let res = [];
348
+ for (let i = 0, len = treeList.length; i < len; i++) {
349
+ const node = treeList[i];
350
+ const item = {
351
+ ...node,
352
+ [childField]: [] // 清空子级
353
+ };
354
+ objectHas(item, childField) && delete item[childField];
355
+ res.push(item);
356
+ if (node[childField]) {
357
+ const children = node[childField].map(item => ({
358
+ ...item,
359
+ [pidField]: node[keyField] || item.pid // 给子级设置pid
360
+ }));
361
+ res = res.concat(flatTree(children, options));
293
362
  }
294
- return res;
363
+ }
364
+ return res;
295
365
  }
296
366
  /**
297
367
  * 模糊搜索函数,返回包含搜索字符的节点及其祖先节点, 适用于树型组件的字符过滤功能
@@ -313,50 +383,49 @@ function flatTree(treeList, options = defaultFieldOptions) {
313
383
  * @returns {V[]}
314
384
  */
315
385
  function fuzzySearchTree(nodes, filterCondition, options = defaultSearchTreeOptions) {
316
- if (!objectHas(filterCondition, 'filter') &&
317
- (!objectHas(filterCondition, 'keyword') || isEmpty(filterCondition.keyword))) {
318
- return nodes;
319
- }
320
- const result = [];
321
- for (let i = 0, len = nodes.length; i < len; i++) {
322
- const node = nodes[i];
323
- // 递归检查子节点是否匹配
324
- const matchedChildren = node[options.childField] && node[options.childField].length > 0
325
- ? fuzzySearchTree(node[options.childField] || [], filterCondition, options)
326
- : [];
327
- // 检查当前节点是否匹配或者有匹配的子节点
328
- if ((objectHas(filterCondition, 'filter')
329
- ? filterCondition.filter(node)
330
- : !options.ignoreCase
331
- ? node[options.nameField].includes(filterCondition.keyword)
332
- : node[options.nameField].toLowerCase().includes(filterCondition.keyword.toLowerCase())) ||
333
- matchedChildren.length > 0) {
334
- // 将当前节点加入结果中
335
- if (node[options.childField]) {
336
- if (matchedChildren.length > 0) {
337
- result.push({
338
- ...node,
339
- [options.childField]: matchedChildren // 包含匹配的子节点
340
- });
341
- }
342
- else if (options.removeEmptyChild) {
343
- const { [options.childField]: _, ...other } = node;
344
- result.push(other);
345
- }
346
- else {
347
- result.push({
348
- ...node,
349
- [options.childField]: []
350
- });
351
- }
352
- }
353
- else {
354
- const { [options.childField]: _, ...other } = node;
355
- result.push(other);
356
- }
386
+ if (!objectHas(filterCondition, 'filter') && !filterCondition.keyword) {
387
+ return nodes;
388
+ }
389
+ const result = [];
390
+ for (let i = 0, len = nodes.length; i < len; i++) {
391
+ const node = nodes[i];
392
+ // 递归检查子节点是否匹配
393
+ const matchedChildren =
394
+ node[options.childField] && node[options.childField].length > 0
395
+ ? fuzzySearchTree(node[options.childField] || [], filterCondition, options)
396
+ : [];
397
+ // 检查当前节点是否匹配或者有匹配的子节点
398
+ if (
399
+ (objectHas(filterCondition, 'filter')
400
+ ? filterCondition.filter(node)
401
+ : !options.ignoreCase
402
+ ? node[options.nameField].includes(filterCondition.keyword)
403
+ : node[options.nameField].toLowerCase().includes(filterCondition.keyword.toLowerCase())) ||
404
+ matchedChildren.length > 0
405
+ ) {
406
+ // 将当前节点加入结果中
407
+ if (node[options.childField]) {
408
+ if (matchedChildren.length > 0) {
409
+ result.push({
410
+ ...node,
411
+ [options.childField]: matchedChildren // 包含匹配的子节点
412
+ });
413
+ } else if (options.removeEmptyChild) {
414
+ const { [options.childField]: _, ...other } = node;
415
+ result.push(other);
416
+ } else {
417
+ result.push({
418
+ ...node,
419
+ [options.childField]: []
420
+ });
357
421
  }
422
+ } else {
423
+ const { [options.childField]: _, ...other } = node;
424
+ result.push(other);
425
+ }
358
426
  }
359
- return result;
427
+ }
428
+ return result;
360
429
  }
361
430
 
362
- export { flatTree, forEachDeep, formatTree, fuzzySearchTree, mapDeep, searchTreeById };
431
+ export { filterDeep, findDeep, flatTree, forEachDeep, formatTree, fuzzySearchTree, mapDeep, searchTreeById };