sculp-js 1.19.3 → 1.19.5
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/cjs/array.cjs +1 -1
- package/dist/cjs/async.cjs +1 -1
- package/dist/cjs/base64.cjs +1 -1
- package/dist/cjs/clipboard.cjs +1 -1
- package/dist/cjs/cloneDeep.cjs +1 -1
- package/dist/cjs/cookie.cjs +1 -1
- package/dist/cjs/date.cjs +17 -65
- package/dist/cjs/dom.cjs +1 -1
- package/dist/cjs/download.cjs +1 -1
- package/dist/cjs/file.cjs +2 -2
- package/dist/cjs/func.cjs +1 -1
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/isEqual.cjs +1 -1
- package/dist/cjs/math.cjs +1 -1
- package/dist/cjs/number.cjs +1 -1
- package/dist/cjs/object.cjs +1 -1
- package/dist/cjs/path.cjs +1 -1
- package/dist/cjs/qs.cjs +1 -1
- package/dist/cjs/random.cjs +1 -1
- package/dist/cjs/string.cjs +10 -7
- package/dist/cjs/tooltip.cjs +1 -1
- package/dist/cjs/tree.cjs +159 -180
- package/dist/cjs/type.cjs +1 -1
- package/dist/cjs/unicodeToolkit.cjs +3 -3
- package/dist/cjs/unique.cjs +1 -1
- package/dist/cjs/url.cjs +1 -1
- package/dist/cjs/validator.cjs +1 -1
- package/dist/cjs/variable.cjs +1 -1
- package/dist/cjs/watermark.cjs +1 -1
- package/dist/esm/array.mjs +1 -1
- package/dist/esm/async.mjs +1 -1
- package/dist/esm/base64.mjs +1 -1
- package/dist/esm/clipboard.mjs +1 -1
- package/dist/esm/cloneDeep.mjs +1 -1
- package/dist/esm/cookie.mjs +1 -1
- package/dist/esm/date.mjs +17 -65
- package/dist/esm/dom.mjs +1 -1
- package/dist/esm/download.mjs +1 -1
- package/dist/esm/file.mjs +2 -2
- package/dist/esm/func.mjs +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/isEqual.mjs +1 -1
- package/dist/esm/math.mjs +1 -1
- package/dist/esm/number.mjs +1 -1
- package/dist/esm/object.mjs +1 -1
- package/dist/esm/path.mjs +1 -1
- package/dist/esm/qs.mjs +1 -1
- package/dist/esm/random.mjs +1 -1
- package/dist/esm/string.mjs +10 -7
- package/dist/esm/tooltip.mjs +1 -1
- package/dist/esm/tree.mjs +159 -180
- package/dist/esm/type.mjs +1 -1
- package/dist/esm/unicodeToolkit.mjs +3 -3
- package/dist/esm/unique.mjs +1 -1
- package/dist/esm/url.mjs +1 -1
- package/dist/esm/validator.mjs +1 -1
- package/dist/esm/variable.mjs +1 -1
- package/dist/esm/watermark.mjs +1 -1
- package/dist/sculp-js.d.ts +2275 -0
- package/dist/types/date.d.ts +21 -57
- package/dist/types/file.d.ts +1 -1
- package/dist/types/tree.d.ts +12 -12
- package/dist/types/tsdoc-metadata.json +11 -0
- package/dist/types/unicodeToolkit.d.ts +2 -2
- package/dist/umd/index.min.js +2 -2
- package/package.json +147 -117
package/dist/cjs/tree.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.19.
|
|
2
|
+
* sculp-js v1.19.5
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -18,10 +18,15 @@ const defaultSearchTreeOptions = {
|
|
|
18
18
|
removeEmptyChild: false,
|
|
19
19
|
ignoreCase: true
|
|
20
20
|
};
|
|
21
|
+
function getChildNodes(item, childField, isDomNode) {
|
|
22
|
+
const child = item[childField];
|
|
23
|
+
if (!child) return null;
|
|
24
|
+
return isDomNode && type.isNodeList(child) ? Array.from(child) : Array.isArray(child) ? child : null;
|
|
25
|
+
}
|
|
21
26
|
/**
|
|
22
|
-
*
|
|
27
|
+
* 深度遍历函数 (支持 continue 和 break 操作), 可用于遍历 Array 和 NodeList 类型的数据
|
|
23
28
|
* @param {ArrayLike<V>} tree 树形数据
|
|
24
|
-
* @param {Function} iterator
|
|
29
|
+
* @param {Function} iterator 迭代函数,返回值为 true 时 continue, 返回值为 false 时 break
|
|
25
30
|
* @param {options} options 支持定制子元素名称、反向遍历、广度优先遍历,默认{
|
|
26
31
|
childField: 'children',
|
|
27
32
|
reverse: false,
|
|
@@ -48,93 +53,56 @@ function forEachDeep(
|
|
|
48
53
|
} = type.isObject(options) ? options : {};
|
|
49
54
|
let isBreak = false;
|
|
50
55
|
const queue = [];
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const item = arr[index];
|
|
57
|
-
// 广度优先
|
|
58
|
-
if (breadthFirst) {
|
|
59
|
-
queue.push({ item, index, array: arr, tree, parent, level });
|
|
60
|
-
} else {
|
|
61
|
-
const re = iterator(item, index, arr, tree, parent, level);
|
|
62
|
-
if (re === false) {
|
|
63
|
-
isBreak = true;
|
|
64
|
-
break;
|
|
65
|
-
} else if (re === true) {
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
if (item && (isDomNode ? type.isNodeList(item[childField]) : Array.isArray(item[childField]))) {
|
|
69
|
-
reverseWalk(item[childField], item, level + 1);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
56
|
+
const processNode = (item, index, arr, parent, level) => {
|
|
57
|
+
const re = iterator(item, index, arr, tree, parent, level);
|
|
58
|
+
if (re === false) {
|
|
59
|
+
isBreak = true;
|
|
60
|
+
return;
|
|
72
61
|
}
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
break;
|
|
82
|
-
} else if (re === true) {
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
if (item && (isDomNode ? type.isNodeList(item[childField]) : Array.isArray(item[childField]))) {
|
|
86
|
-
reverseWalk(item[childField], item, level + 1);
|
|
62
|
+
if (re === true) return;
|
|
63
|
+
const childNodes = getChildNodes(item, childField, isDomNode);
|
|
64
|
+
if (childNodes) {
|
|
65
|
+
if (breadthFirst) {
|
|
66
|
+
// BFS: 将子节点加入队列
|
|
67
|
+
const childLen = childNodes.length;
|
|
68
|
+
for (let i = 0; i < childLen; i++) {
|
|
69
|
+
queue.push({ item: childNodes[i], index: i, array: childNodes, tree, parent: item, level: level + 1 });
|
|
87
70
|
}
|
|
71
|
+
} else {
|
|
72
|
+
// DFS: 立即递归处理子节点
|
|
73
|
+
walk(childNodes, item, level + 1);
|
|
88
74
|
}
|
|
89
75
|
}
|
|
90
76
|
};
|
|
91
|
-
const walk = (arr, parent, level
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (breadthFirst) {
|
|
98
|
-
// 广度优先
|
|
99
|
-
queue.push({ item, index: index, array: arr, tree, parent, level });
|
|
100
|
-
} else {
|
|
101
|
-
// 深度优先
|
|
102
|
-
const re = iterator(item, index, arr, tree, parent, level);
|
|
103
|
-
if (re === false) {
|
|
104
|
-
isBreak = true;
|
|
105
|
-
break;
|
|
106
|
-
} else if (re === true) {
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
if (item && (isDomNode ? type.isNodeList(item[childField]) : Array.isArray(item[childField]))) {
|
|
110
|
-
walk(item[childField], item, level + 1);
|
|
111
|
-
}
|
|
77
|
+
const walk = (arr, parent, level) => {
|
|
78
|
+
const len = arr.length;
|
|
79
|
+
if (reverse) {
|
|
80
|
+
for (let i = len - 1; i >= 0; i--) {
|
|
81
|
+
if (isBreak) break;
|
|
82
|
+
processNode(arr[i], i, arr, parent, level);
|
|
112
83
|
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (!current) break;
|
|
118
|
-
const { item, index, array, tree, parent, level } = current;
|
|
119
|
-
const re = iterator(item, index, array, tree, parent, level);
|
|
120
|
-
if (re === false) {
|
|
121
|
-
isBreak = true;
|
|
122
|
-
break;
|
|
123
|
-
} else if (re === true) {
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
if (item && (isDomNode ? type.isNodeList(item[childField]) : Array.isArray(item[childField]))) {
|
|
127
|
-
walk(item[childField], item, level + 1);
|
|
128
|
-
}
|
|
84
|
+
} else {
|
|
85
|
+
for (let i = 0; i < len; i++) {
|
|
86
|
+
if (isBreak) break;
|
|
87
|
+
processNode(arr[i], i, arr, parent, level);
|
|
129
88
|
}
|
|
130
89
|
}
|
|
131
90
|
};
|
|
132
|
-
|
|
91
|
+
// 先处理根节点
|
|
92
|
+
walk(tree, null, 0);
|
|
93
|
+
// BFS: 处理队列中的节点
|
|
94
|
+
if (breadthFirst) {
|
|
95
|
+
let queueIndex = 0;
|
|
96
|
+
while (queueIndex < queue.length && !isBreak) {
|
|
97
|
+
const { item, index, array, parent, level } = queue[queueIndex++];
|
|
98
|
+
processNode(item, index, array, parent, level);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
133
101
|
// @ts-ignore
|
|
134
102
|
tree = null;
|
|
135
103
|
}
|
|
136
104
|
/**
|
|
137
|
-
*
|
|
105
|
+
* 树查找函数,可用于查找 Array 和 NodeList 类型的数据
|
|
138
106
|
* @param {ArrayLike<V>} tree 树形数据
|
|
139
107
|
* @param {Function} predicate 断言函数
|
|
140
108
|
* @param {options} options 支持定制子元素名称、反向遍历、广度优先遍历,默认{
|
|
@@ -169,7 +137,7 @@ function findDeep(
|
|
|
169
137
|
return result;
|
|
170
138
|
}
|
|
171
139
|
/**
|
|
172
|
-
*
|
|
140
|
+
* 树过滤函数,可用于过滤 Array 和 NodeList 类型的数据
|
|
173
141
|
* @param {ArrayLike<V>} tree 树形数据
|
|
174
142
|
* @param {Function} predicate 断言函数
|
|
175
143
|
* @param {options} options 支持定制子元素名称、反向遍历、广度优先遍历,默认{
|
|
@@ -203,11 +171,11 @@ function filterDeep(
|
|
|
203
171
|
return result;
|
|
204
172
|
}
|
|
205
173
|
/**
|
|
206
|
-
*
|
|
174
|
+
* 创建一个新数组,深度优先遍历的 Map 函数 (支持 continue 和 break 操作), 可用于 insert tree item 和 remove tree item
|
|
207
175
|
*
|
|
208
176
|
* 可遍历任何带有 length 属性和数字键的类数组对象
|
|
209
177
|
* @param {ArrayLike<V>} tree 树形数据
|
|
210
|
-
* @param {Function} iterator
|
|
178
|
+
* @param {Function} iterator 迭代函数,返回值为 true 时 continue, 返回值为 false 时 break
|
|
211
179
|
* @param {options} options 支持定制子元素名称、反向遍历,默认{
|
|
212
180
|
childField: 'children',
|
|
213
181
|
reverse: false,
|
|
@@ -225,54 +193,46 @@ function mapDeep(
|
|
|
225
193
|
const { childField = 'children', reverse = false } = type.isObject(options) ? options : {};
|
|
226
194
|
let isBreak = false;
|
|
227
195
|
const newTree = [];
|
|
228
|
-
const walk = (arr, parent,
|
|
196
|
+
const walk = (arr, parent, output, level) => {
|
|
229
197
|
if (reverse) {
|
|
230
198
|
for (let i = arr.length - 1; i >= 0; i--) {
|
|
231
|
-
if (isBreak)
|
|
232
|
-
break;
|
|
233
|
-
}
|
|
199
|
+
if (isBreak) break;
|
|
234
200
|
const item = arr[i];
|
|
235
201
|
const re = iterator(item, i, arr, tree, parent, level);
|
|
236
202
|
if (re === false) {
|
|
237
203
|
isBreak = true;
|
|
238
204
|
break;
|
|
239
|
-
} else if (re === true) {
|
|
240
|
-
continue;
|
|
241
205
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
206
|
+
if (re === true) continue;
|
|
207
|
+
const newItem = object.objectOmit(re, [childField]);
|
|
208
|
+
output.push(newItem);
|
|
209
|
+
const children = item[childField];
|
|
210
|
+
if (Array.isArray(children)) {
|
|
211
|
+
newItem[childField] = [];
|
|
212
|
+
walk(children, item, newItem[childField], level + 1);
|
|
249
213
|
}
|
|
250
214
|
}
|
|
251
215
|
} else {
|
|
252
216
|
for (let i = 0; i < arr.length; i++) {
|
|
253
|
-
if (isBreak)
|
|
254
|
-
break;
|
|
255
|
-
}
|
|
217
|
+
if (isBreak) break;
|
|
256
218
|
const item = arr[i];
|
|
257
219
|
const re = iterator(item, i, arr, tree, parent, level);
|
|
258
220
|
if (re === false) {
|
|
259
221
|
isBreak = true;
|
|
260
222
|
break;
|
|
261
|
-
} else if (re === true) {
|
|
262
|
-
continue;
|
|
263
223
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
224
|
+
if (re === true) continue;
|
|
225
|
+
const newItem = object.objectOmit(re, [childField]);
|
|
226
|
+
output.push(newItem);
|
|
227
|
+
const children = item[childField];
|
|
228
|
+
if (Array.isArray(children)) {
|
|
229
|
+
newItem[childField] = [];
|
|
230
|
+
walk(children, item, newItem[childField], level + 1);
|
|
271
231
|
}
|
|
272
232
|
}
|
|
273
233
|
}
|
|
274
234
|
};
|
|
275
|
-
walk(tree, null, newTree);
|
|
235
|
+
walk(tree, null, newTree, 0);
|
|
276
236
|
// @ts-ignore
|
|
277
237
|
tree = null;
|
|
278
238
|
return newTree;
|
|
@@ -281,40 +241,51 @@ function mapDeep(
|
|
|
281
241
|
* 在树中找到 id 为某个值的节点,并返回上游的所有父级节点
|
|
282
242
|
*
|
|
283
243
|
* @param {ArrayLike<T>} tree - 树形数据
|
|
284
|
-
* @param {number | string} nodeId - 目标元素ID
|
|
285
|
-
* @param {ITreeConf} options -
|
|
286
|
-
* @returns {[(number | string)[], V[]]} - 由parentId...childId, parentObject-childObject组成的二维数组
|
|
244
|
+
* @param {number | string} nodeId - 目标元素 ID
|
|
245
|
+
* @param {ITreeConf} options - 迭代配置项,默认:{ children = 'children', id = 'id' }
|
|
246
|
+
* @returns {[(number | string)[], V[]]} - 由 parentId...childId, parentObject-childObject 组成的二维数组
|
|
287
247
|
*/
|
|
288
248
|
function searchTreeById(tree, nodeId, options = { childField: 'children', keyField: 'id' }) {
|
|
289
249
|
const { childField = 'children', keyField = 'id' } = type.isObject(options) ? options : {};
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
nodes = [child.parent, ...nodes];
|
|
308
|
-
child = flatArray.find(_ => _[keyField] === child.parentId); // eslint-disable-line
|
|
250
|
+
const flatMap = {};
|
|
251
|
+
// 扁平化 - 使用迭代而非递归,避免栈溢出
|
|
252
|
+
const stack = [];
|
|
253
|
+
const len = tree.length;
|
|
254
|
+
for (let i = 0; i < len; i++) {
|
|
255
|
+
stack.push({ node: tree[i] });
|
|
256
|
+
}
|
|
257
|
+
while (stack.length > 0) {
|
|
258
|
+
const { node, parentId, parent } = stack.pop();
|
|
259
|
+
const id = node[keyField];
|
|
260
|
+
flatMap[id] = { node, parentId, parent };
|
|
261
|
+
const children = node[childField];
|
|
262
|
+
if (Array.isArray(children)) {
|
|
263
|
+
const childLen = children.length;
|
|
264
|
+
for (let i = 0; i < childLen; i++) {
|
|
265
|
+
stack.push({ node: children[i], parentId: id, parent: node });
|
|
266
|
+
}
|
|
309
267
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
268
|
+
}
|
|
269
|
+
// 回溯路径
|
|
270
|
+
const ids = [];
|
|
271
|
+
const nodes = [];
|
|
272
|
+
let current = flatMap[nodeId];
|
|
273
|
+
if (!current) return [[], []];
|
|
274
|
+
ids.push(nodeId);
|
|
275
|
+
nodes.push(current.node);
|
|
276
|
+
while (current && current.parentId !== undefined) {
|
|
277
|
+
ids.unshift(current.parentId);
|
|
278
|
+
const parent = flatMap[current.parentId];
|
|
279
|
+
if (!parent) break;
|
|
280
|
+
nodes.unshift(parent.node);
|
|
281
|
+
current = parent;
|
|
282
|
+
}
|
|
283
|
+
return [ids, nodes];
|
|
313
284
|
}
|
|
314
285
|
/**
|
|
315
286
|
* 扁平化数组转换成树
|
|
316
287
|
* @param {any[]} list
|
|
317
|
-
* @param {IFieldOptions} options 定制id字段名,子元素字段名,父元素字段名,默认
|
|
288
|
+
* @param {IFieldOptions} options 定制 id 字段名,子元素字段名,父元素字段名,默认
|
|
318
289
|
* { keyField: 'key', childField: 'children', pidField: 'pid' }
|
|
319
290
|
* @returns {any[]}
|
|
320
291
|
*/
|
|
@@ -322,11 +293,13 @@ function formatTree(list, options = defaultFieldOptions) {
|
|
|
322
293
|
const { keyField = 'key', childField = 'children', pidField = 'pid' } = type.isObject(options) ? options : {};
|
|
323
294
|
const treeArr = [];
|
|
324
295
|
const sourceMap = {};
|
|
325
|
-
|
|
296
|
+
const len = list.length;
|
|
297
|
+
// 先克隆所有对象,避免修改源数据
|
|
298
|
+
for (let i = 0; i < len; i++) {
|
|
326
299
|
const item = list[i];
|
|
327
300
|
sourceMap[item[keyField]] = item;
|
|
328
301
|
}
|
|
329
|
-
for (let i = 0
|
|
302
|
+
for (let i = 0; i < len; i++) {
|
|
330
303
|
const item = list[i];
|
|
331
304
|
const parent = sourceMap[item[pidField]];
|
|
332
305
|
if (parent) {
|
|
@@ -342,29 +315,32 @@ function formatTree(list, options = defaultFieldOptions) {
|
|
|
342
315
|
/**
|
|
343
316
|
* 树形结构转扁平化
|
|
344
317
|
* @param {any[]} treeList
|
|
345
|
-
* @param {IFieldOptions} options 定制id字段名,子元素字段名,父元素字段名,默认
|
|
318
|
+
* @param {IFieldOptions} options 定制 id 字段名,子元素字段名,父元素字段名,默认
|
|
346
319
|
* { keyField: 'key', childField: 'children', pidField: 'pid' }
|
|
347
320
|
* @returns {any[]}
|
|
348
321
|
*/
|
|
349
322
|
function flatTree(treeList, options = defaultFieldOptions) {
|
|
350
323
|
const { keyField = 'key', childField = 'children', pidField = 'pid' } = type.isObject(options) ? options : {};
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
324
|
+
const res = [];
|
|
325
|
+
const walk = nodes => {
|
|
326
|
+
const len = nodes.length;
|
|
327
|
+
for (let i = 0; i < len; i++) {
|
|
328
|
+
const node = nodes[i];
|
|
329
|
+
const item = { ...node };
|
|
330
|
+
delete item[childField];
|
|
331
|
+
res.push(item);
|
|
332
|
+
const children = node[childField];
|
|
333
|
+
if (Array.isArray(children)) {
|
|
334
|
+
// 创建新的子节点数组,不修改原数据
|
|
335
|
+
const newChildren = children.map(child => ({
|
|
336
|
+
...child,
|
|
337
|
+
[pidField]: node[keyField] !== undefined ? node[keyField] : child.pid
|
|
338
|
+
}));
|
|
339
|
+
walk(newChildren);
|
|
340
|
+
}
|
|
366
341
|
}
|
|
367
|
-
}
|
|
342
|
+
};
|
|
343
|
+
walk(treeList);
|
|
368
344
|
return res;
|
|
369
345
|
}
|
|
370
346
|
/**
|
|
@@ -391,41 +367,44 @@ function fuzzySearchTree(nodes, filterCondition, options = defaultSearchTreeOpti
|
|
|
391
367
|
return nodes;
|
|
392
368
|
}
|
|
393
369
|
const result = [];
|
|
370
|
+
const { childField, nameField, removeEmptyChild, ignoreCase } = options;
|
|
371
|
+
const hasFilter = type.objectHas(filterCondition, 'filter');
|
|
372
|
+
const filterFn = filterCondition.filter;
|
|
373
|
+
const keyword = filterCondition.keyword;
|
|
394
374
|
for (let i = 0, len = nodes.length; i < len; i++) {
|
|
395
375
|
const node = nodes[i];
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
376
|
+
const children = node[childField];
|
|
377
|
+
// 递归处理子节点
|
|
378
|
+
const matchedChildren = children && children.length > 0 ? fuzzySearchTree(children, filterCondition, options) : [];
|
|
379
|
+
// 判断当前节点是否匹配
|
|
380
|
+
let isMatch = false;
|
|
381
|
+
if (hasFilter && filterFn) {
|
|
382
|
+
isMatch = filterFn(node);
|
|
383
|
+
} else if (keyword !== undefined && keyword !== null) {
|
|
384
|
+
const nodeValue = String(node[nameField] || '');
|
|
385
|
+
const searchValue = String(keyword);
|
|
386
|
+
isMatch = ignoreCase
|
|
387
|
+
? nodeValue.toLowerCase().includes(searchValue.toLowerCase())
|
|
388
|
+
: nodeValue.includes(searchValue);
|
|
389
|
+
}
|
|
390
|
+
// 如果当前节点匹配或有匹配的子节点,则加入结果
|
|
391
|
+
if (isMatch || matchedChildren.length > 0) {
|
|
392
|
+
if (childField in node) {
|
|
393
|
+
// 节点有 children 字段
|
|
412
394
|
if (matchedChildren.length > 0) {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
result.push(other);
|
|
395
|
+
// 有匹配的子节点
|
|
396
|
+
result.push({ ...node, [childField]: matchedChildren });
|
|
397
|
+
} else if (removeEmptyChild) {
|
|
398
|
+
// 无匹配子节点且需要移除空 children
|
|
399
|
+
const { [childField]: _, ...rest } = node;
|
|
400
|
+
result.push(rest);
|
|
420
401
|
} else {
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
[options.childField]: []
|
|
424
|
-
});
|
|
402
|
+
// 无匹配子节点但保留 children 字段(设为空数组)
|
|
403
|
+
result.push({ ...node, [childField]: [] });
|
|
425
404
|
}
|
|
426
405
|
} else {
|
|
427
|
-
|
|
428
|
-
result.push(
|
|
406
|
+
// 节点没有 children 字段,直接返回
|
|
407
|
+
result.push(node);
|
|
429
408
|
}
|
|
430
409
|
}
|
|
431
410
|
}
|
package/dist/cjs/type.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.19.
|
|
2
|
+
* sculp-js v1.19.5
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -23,12 +23,12 @@ class UnicodeToolkit {
|
|
|
23
23
|
* UnicodeToolkit.encode('Hi 你好 😀')
|
|
24
24
|
* // => 'Hi \u4F60\u597D \u{1F600}'
|
|
25
25
|
* @example
|
|
26
|
-
* // 全部Unicode 编码
|
|
26
|
+
* // 全部 Unicode 编码
|
|
27
27
|
* UnicodeToolkit.encode('Hi 你好 😀','unicode', true)
|
|
28
28
|
* // => '\u0048\u0069\u0020\u4F60\u597D\u0020\u{1F600}'
|
|
29
29
|
* @example
|
|
30
30
|
* // HTML 实体编码
|
|
31
|
-
* UnicodeToolkit.encode('<
|
|
31
|
+
* UnicodeToolkit.encode('<scr' + 'ipt>', 'html',true)
|
|
32
32
|
* // => '<script>&'
|
|
33
33
|
*/
|
|
34
34
|
static encode(str, mode = 'unicode', encodeAll = false) {
|
package/dist/cjs/unique.cjs
CHANGED
package/dist/cjs/url.cjs
CHANGED
package/dist/cjs/validator.cjs
CHANGED
package/dist/cjs/variable.cjs
CHANGED
package/dist/cjs/watermark.cjs
CHANGED
package/dist/esm/array.mjs
CHANGED
package/dist/esm/async.mjs
CHANGED
package/dist/esm/base64.mjs
CHANGED
package/dist/esm/clipboard.mjs
CHANGED
package/dist/esm/cloneDeep.mjs
CHANGED
package/dist/esm/cookie.mjs
CHANGED