onchain-utility 0.0.15 → 0.0.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/Hooks.js +14 -0
- package/dist/Hooks.mjs +14 -0
- package/dist/OnchainUtility.js +190 -4
- package/dist/OnchainUtility.mjs +178 -5
- package/dist/Tree.js +117 -4
- package/dist/Tree.mjs +115 -5
- package/package.json +1 -1
- package/src/Tree/index.ts +167 -18
- package/src/base.ts +68 -0
package/dist/Hooks.js
CHANGED
|
@@ -87,6 +87,7 @@ var useUpdate = function () {
|
|
|
87
87
|
*/
|
|
88
88
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
89
89
|
|
|
90
|
+
/** 是否是Moment对象(_表示为内部函数谨慎使用) */
|
|
90
91
|
function _isMoment(obj) {
|
|
91
92
|
return obj != null && typeof obj === 'object' &&
|
|
92
93
|
// 检查内部标志
|
|
@@ -96,6 +97,13 @@ function _isMoment(obj) {
|
|
|
96
97
|
// 检查内部属性
|
|
97
98
|
'_d' in obj && '_i' in obj;
|
|
98
99
|
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 创建一个可解构的对象,该对象同时具有原始对象的属性和数组的迭代器,使其可以使用对象和数组两种解构方式
|
|
103
|
+
* @param obj - 需要转换的对象
|
|
104
|
+
* @param arr - 用于提供迭代器的数组
|
|
105
|
+
* @returns 一个结合了对象属性和数组迭代器的新对象
|
|
106
|
+
*/
|
|
99
107
|
function makeDestructurable(obj, arr) {
|
|
100
108
|
if (typeof Symbol !== 'undefined') {
|
|
101
109
|
const clone = {
|
|
@@ -118,6 +126,8 @@ function makeDestructurable(obj, arr) {
|
|
|
118
126
|
return Object.assign([...arr], obj);
|
|
119
127
|
}
|
|
120
128
|
}
|
|
129
|
+
|
|
130
|
+
/** 创建对象枚举,可以避免两个相同枚举缺不相等 */
|
|
121
131
|
function createEnumObject(o) {
|
|
122
132
|
return o;
|
|
123
133
|
}
|
|
@@ -128,9 +138,13 @@ function toRawType(value) {
|
|
|
128
138
|
// 从字符串中提取“RawType”,如“[object RawType]”
|
|
129
139
|
return toTypeString(value).slice(8, -1);
|
|
130
140
|
}
|
|
141
|
+
|
|
142
|
+
/** 判断对象是否有某个属性 */
|
|
131
143
|
function hasOwnProperty(data, key) {
|
|
132
144
|
return data && Object.prototype.hasOwnProperty.call(data, key);
|
|
133
145
|
}
|
|
146
|
+
|
|
147
|
+
/** 是否是整型key */
|
|
134
148
|
function isIntegerKey(key) {
|
|
135
149
|
return typeof key === 'string' && key !== 'NaN' && key[0] !== '-' && '' + parseInt(key, 10) === key;
|
|
136
150
|
}
|
package/dist/Hooks.mjs
CHANGED
|
@@ -85,6 +85,7 @@ var useUpdate = function () {
|
|
|
85
85
|
*/
|
|
86
86
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
87
87
|
|
|
88
|
+
/** 是否是Moment对象(_表示为内部函数谨慎使用) */
|
|
88
89
|
function _isMoment(obj) {
|
|
89
90
|
return obj != null && typeof obj === 'object' &&
|
|
90
91
|
// 检查内部标志
|
|
@@ -94,6 +95,13 @@ function _isMoment(obj) {
|
|
|
94
95
|
// 检查内部属性
|
|
95
96
|
'_d' in obj && '_i' in obj;
|
|
96
97
|
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 创建一个可解构的对象,该对象同时具有原始对象的属性和数组的迭代器,使其可以使用对象和数组两种解构方式
|
|
101
|
+
* @param obj - 需要转换的对象
|
|
102
|
+
* @param arr - 用于提供迭代器的数组
|
|
103
|
+
* @returns 一个结合了对象属性和数组迭代器的新对象
|
|
104
|
+
*/
|
|
97
105
|
function makeDestructurable(obj, arr) {
|
|
98
106
|
if (typeof Symbol !== 'undefined') {
|
|
99
107
|
const clone = {
|
|
@@ -116,6 +124,8 @@ function makeDestructurable(obj, arr) {
|
|
|
116
124
|
return Object.assign([...arr], obj);
|
|
117
125
|
}
|
|
118
126
|
}
|
|
127
|
+
|
|
128
|
+
/** 创建对象枚举,可以避免两个相同枚举缺不相等 */
|
|
119
129
|
function createEnumObject(o) {
|
|
120
130
|
return o;
|
|
121
131
|
}
|
|
@@ -126,9 +136,13 @@ function toRawType(value) {
|
|
|
126
136
|
// 从字符串中提取“RawType”,如“[object RawType]”
|
|
127
137
|
return toTypeString(value).slice(8, -1);
|
|
128
138
|
}
|
|
139
|
+
|
|
140
|
+
/** 判断对象是否有某个属性 */
|
|
129
141
|
function hasOwnProperty(data, key) {
|
|
130
142
|
return data && Object.prototype.hasOwnProperty.call(data, key);
|
|
131
143
|
}
|
|
144
|
+
|
|
145
|
+
/** 是否是整型key */
|
|
132
146
|
function isIntegerKey(key) {
|
|
133
147
|
return typeof key === 'string' && key !== 'NaN' && key[0] !== '-' && '' + parseInt(key, 10) === key;
|
|
134
148
|
}
|
package/dist/OnchainUtility.js
CHANGED
|
@@ -19,6 +19,7 @@ var react = require('react');
|
|
|
19
19
|
*/
|
|
20
20
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
21
21
|
|
|
22
|
+
/** 是否是Moment对象(_表示为内部函数谨慎使用) */
|
|
22
23
|
function _isMoment(obj) {
|
|
23
24
|
return obj != null && typeof obj === 'object' &&
|
|
24
25
|
// 检查内部标志
|
|
@@ -28,6 +29,13 @@ function _isMoment(obj) {
|
|
|
28
29
|
// 检查内部属性
|
|
29
30
|
'_d' in obj && '_i' in obj;
|
|
30
31
|
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 创建一个可解构的对象,该对象同时具有原始对象的属性和数组的迭代器,使其可以使用对象和数组两种解构方式
|
|
35
|
+
* @param obj - 需要转换的对象
|
|
36
|
+
* @param arr - 用于提供迭代器的数组
|
|
37
|
+
* @returns 一个结合了对象属性和数组迭代器的新对象
|
|
38
|
+
*/
|
|
31
39
|
function makeDestructurable(obj, arr) {
|
|
32
40
|
if (typeof Symbol !== 'undefined') {
|
|
33
41
|
const clone = {
|
|
@@ -50,6 +58,8 @@ function makeDestructurable(obj, arr) {
|
|
|
50
58
|
return Object.assign([...arr], obj);
|
|
51
59
|
}
|
|
52
60
|
}
|
|
61
|
+
|
|
62
|
+
/** 创建对象枚举,可以避免两个相同枚举缺不相等 */
|
|
53
63
|
function createEnumObject(o) {
|
|
54
64
|
return o;
|
|
55
65
|
}
|
|
@@ -60,15 +70,68 @@ function toRawType(value) {
|
|
|
60
70
|
// 从字符串中提取“RawType”,如“[object RawType]”
|
|
61
71
|
return toTypeString(value).slice(8, -1);
|
|
62
72
|
}
|
|
73
|
+
function isString(value) {
|
|
74
|
+
return toRawType(value) === 'String';
|
|
75
|
+
}
|
|
76
|
+
function isNumber(value) {
|
|
77
|
+
return toRawType(value) === 'Number';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** 判断值是否为NaN */
|
|
81
|
+
function isNaN(value) {
|
|
82
|
+
return Number.isNaN(value);
|
|
83
|
+
}
|
|
84
|
+
function isBoolean(value) {
|
|
85
|
+
return toRawType(value) === 'Boolean';
|
|
86
|
+
}
|
|
87
|
+
function isUndefined(value) {
|
|
88
|
+
return toRawType(value) === 'Undefined';
|
|
89
|
+
}
|
|
90
|
+
function isNull(value) {
|
|
91
|
+
return toRawType(value) === 'Null';
|
|
92
|
+
}
|
|
93
|
+
function isNil(value) {
|
|
94
|
+
return isNull(value) || isUndefined(value);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 判断是否是 `null` 或 `undefined`
|
|
99
|
+
* @example
|
|
100
|
+
* _.isNil(null);
|
|
101
|
+
* // => true
|
|
102
|
+
*
|
|
103
|
+
* _.isNil(void 0);
|
|
104
|
+
* // => true
|
|
105
|
+
*
|
|
106
|
+
* _.isNil(NaN);
|
|
107
|
+
* // => false
|
|
108
|
+
*/
|
|
109
|
+
function isObject(value) {
|
|
110
|
+
return toRawType(value) === 'Object';
|
|
111
|
+
}
|
|
112
|
+
function isArray(value) {
|
|
113
|
+
return toRawType(value) === 'Array';
|
|
114
|
+
}
|
|
115
|
+
function isFunction(value) {
|
|
116
|
+
return toRawType(value) === 'Function';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** 判断对象是否有某个属性 */
|
|
63
120
|
function hasOwnProperty(data, key) {
|
|
64
121
|
return data && Object.prototype.hasOwnProperty.call(data, key);
|
|
65
122
|
}
|
|
123
|
+
|
|
124
|
+
/** 是否是整型key */
|
|
66
125
|
function isIntegerKey(key) {
|
|
67
126
|
return typeof key === 'string' && key !== 'NaN' && key[0] !== '-' && '' + parseInt(key, 10) === key;
|
|
68
127
|
}
|
|
128
|
+
|
|
129
|
+
/** 是否是空对象 */
|
|
69
130
|
function isEmptyObject(obj) {
|
|
70
131
|
return obj ? !Object.keys(obj).length : true;
|
|
71
132
|
}
|
|
133
|
+
|
|
134
|
+
/** 生成 innerHTML */
|
|
72
135
|
function getHTMLTagString(params) {
|
|
73
136
|
const attrsString = Object.entries(params.attributes || {}).map(([key, value]) => {
|
|
74
137
|
return ` ${key}="${value}"`;
|
|
@@ -1082,6 +1145,46 @@ function levelTransformTree({
|
|
|
1082
1145
|
});
|
|
1083
1146
|
return root.children;
|
|
1084
1147
|
}
|
|
1148
|
+
|
|
1149
|
+
/** 获取全部子孙节点 */
|
|
1150
|
+
function getTreeDescendants({
|
|
1151
|
+
data,
|
|
1152
|
+
key,
|
|
1153
|
+
signKey = 'id',
|
|
1154
|
+
childrenKey = 'children'
|
|
1155
|
+
}) {
|
|
1156
|
+
const {
|
|
1157
|
+
self
|
|
1158
|
+
} = getTreeRelation({
|
|
1159
|
+
childrenKey,
|
|
1160
|
+
data,
|
|
1161
|
+
lookup(item, index) {
|
|
1162
|
+
return item[signKey] === key;
|
|
1163
|
+
}
|
|
1164
|
+
});
|
|
1165
|
+
return arrayAttributeFlat({
|
|
1166
|
+
childrenKey,
|
|
1167
|
+
data: self?.[childrenKey] || []
|
|
1168
|
+
});
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
/** 获取全部祖先节点 */
|
|
1172
|
+
function getTreeAncestors({
|
|
1173
|
+
data,
|
|
1174
|
+
key,
|
|
1175
|
+
signKey = 'id',
|
|
1176
|
+
childrenKey = 'children'
|
|
1177
|
+
}) {
|
|
1178
|
+
return getTreeRelation({
|
|
1179
|
+
childrenKey,
|
|
1180
|
+
data,
|
|
1181
|
+
lookup(item, index) {
|
|
1182
|
+
return item[signKey] === key;
|
|
1183
|
+
}
|
|
1184
|
+
}).stack;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
/** 删除树节点 */
|
|
1085
1188
|
function deleteTreeNodes({
|
|
1086
1189
|
data,
|
|
1087
1190
|
selectedKeys,
|
|
@@ -1235,6 +1338,51 @@ function getSiblings({
|
|
|
1235
1338
|
return keys;
|
|
1236
1339
|
}
|
|
1237
1340
|
|
|
1341
|
+
/**
|
|
1342
|
+
* @description 是否跨层
|
|
1343
|
+
* @date 2022-11-21 20:03:52
|
|
1344
|
+
* @export
|
|
1345
|
+
* @param {string[]} hierarchy 选中任务的层级
|
|
1346
|
+
* @returns {*}
|
|
1347
|
+
*/
|
|
1348
|
+
function getSelectedNodeHierarchyStatus({
|
|
1349
|
+
data,
|
|
1350
|
+
selectedKeys,
|
|
1351
|
+
signKey = 'id',
|
|
1352
|
+
childrenKey = 'children'
|
|
1353
|
+
}) {
|
|
1354
|
+
const relations = selectedKeys.map(key => getTreeRelation({
|
|
1355
|
+
childrenKey,
|
|
1356
|
+
data,
|
|
1357
|
+
lookup(item, index) {
|
|
1358
|
+
return item[signKey] === key;
|
|
1359
|
+
}
|
|
1360
|
+
}));
|
|
1361
|
+
// 深度集合
|
|
1362
|
+
const deepSet = new Set(relations.map(rel => rel.stack.length));
|
|
1363
|
+
const isDifferentDepths = deepSet.size > 1;
|
|
1364
|
+
if (isDifferentDepths) {
|
|
1365
|
+
return {
|
|
1366
|
+
isDifferentDepths,
|
|
1367
|
+
isIncludedParent: relations.sort((a, b) => {
|
|
1368
|
+
return b.stack.length - a.stack.length;
|
|
1369
|
+
}).some(item => {
|
|
1370
|
+
const ancestors = getTreeAncestors({
|
|
1371
|
+
childrenKey,
|
|
1372
|
+
data,
|
|
1373
|
+
key: item.self[signKey],
|
|
1374
|
+
signKey
|
|
1375
|
+
}).map(item => item[signKey]);
|
|
1376
|
+
return selectedKeys.some(id => ancestors.includes(id));
|
|
1377
|
+
})
|
|
1378
|
+
};
|
|
1379
|
+
}
|
|
1380
|
+
return {
|
|
1381
|
+
isDifferentDepths,
|
|
1382
|
+
isIncludedParent: false
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1238
1386
|
/**
|
|
1239
1387
|
* @description 合并相邻的选中数据
|
|
1240
1388
|
* @date 2023-02-15 16:11:16
|
|
@@ -1353,9 +1501,10 @@ function generatedAcrossHierarchySort({
|
|
|
1353
1501
|
function optimizeStructure({
|
|
1354
1502
|
data,
|
|
1355
1503
|
childrenKey = 'children',
|
|
1356
|
-
signKey = 'id'
|
|
1504
|
+
signKey = 'id',
|
|
1505
|
+
isSupportMultipleRoot = false
|
|
1357
1506
|
}) {
|
|
1358
|
-
if (data.length > 1) {
|
|
1507
|
+
if (data.length > 1 || isSupportMultipleRoot) {
|
|
1359
1508
|
return [{
|
|
1360
1509
|
[childrenKey]: data,
|
|
1361
1510
|
isCustom: true,
|
|
@@ -1460,6 +1609,7 @@ async function upgrade({
|
|
|
1460
1609
|
data,
|
|
1461
1610
|
signKey = 'id',
|
|
1462
1611
|
isFollow,
|
|
1612
|
+
isSupportMultipleRoot = false,
|
|
1463
1613
|
onStopFollow,
|
|
1464
1614
|
onFilterFollow,
|
|
1465
1615
|
onUpgrade,
|
|
@@ -1471,6 +1621,7 @@ async function upgrade({
|
|
|
1471
1621
|
data = optimizeStructure({
|
|
1472
1622
|
childrenKey,
|
|
1473
1623
|
data,
|
|
1624
|
+
isSupportMultipleRoot,
|
|
1474
1625
|
signKey
|
|
1475
1626
|
});
|
|
1476
1627
|
const layers = mergeAdjacent({
|
|
@@ -1556,7 +1707,12 @@ async function upgrade({
|
|
|
1556
1707
|
});
|
|
1557
1708
|
const insert = (data, index) => {
|
|
1558
1709
|
data.splice(index, 0, ...selected);
|
|
1559
|
-
onUpgraded?.(selected
|
|
1710
|
+
onUpgraded?.(selected, getExpandedState({
|
|
1711
|
+
childrenKey,
|
|
1712
|
+
originalParent: parent,
|
|
1713
|
+
parent: grandpa,
|
|
1714
|
+
signKey
|
|
1715
|
+
}));
|
|
1560
1716
|
};
|
|
1561
1717
|
const insertIndex = getInsertIdx({
|
|
1562
1718
|
leader: start,
|
|
@@ -1618,7 +1774,12 @@ async function downgrade({
|
|
|
1618
1774
|
const newChildren = [...(before[childrenKey] || []), ...children];
|
|
1619
1775
|
if (children.length) {
|
|
1620
1776
|
before[childrenKey] = [...newChildren];
|
|
1621
|
-
onDowngraded?.(children
|
|
1777
|
+
onDowngraded?.(children, getExpandedState({
|
|
1778
|
+
childrenKey,
|
|
1779
|
+
originalParent: parent,
|
|
1780
|
+
parent: before,
|
|
1781
|
+
signKey
|
|
1782
|
+
}));
|
|
1622
1783
|
}
|
|
1623
1784
|
}
|
|
1624
1785
|
}
|
|
@@ -1671,6 +1832,18 @@ function treeSearch({
|
|
|
1671
1832
|
}
|
|
1672
1833
|
}).filter(row => !!row);
|
|
1673
1834
|
}
|
|
1835
|
+
function getExpandedState({
|
|
1836
|
+
originalParent,
|
|
1837
|
+
parent,
|
|
1838
|
+
signKey = 'id',
|
|
1839
|
+
childrenKey = 'children'
|
|
1840
|
+
}) {
|
|
1841
|
+
const isRemove = !originalParent[childrenKey]?.length;
|
|
1842
|
+
return {
|
|
1843
|
+
add: parent[signKey],
|
|
1844
|
+
remove: isRemove ? originalParent[signKey] : null
|
|
1845
|
+
};
|
|
1846
|
+
}
|
|
1674
1847
|
|
|
1675
1848
|
exports._isMoment = _isMoment;
|
|
1676
1849
|
exports.arrayAttributeFlat = arrayAttributeFlat;
|
|
@@ -1689,13 +1862,26 @@ exports.generatedAcrossHierarchySort = generatedAcrossHierarchySort;
|
|
|
1689
1862
|
exports.getBase64Regular = getBase64Regular;
|
|
1690
1863
|
exports.getHTMLTagString = getHTMLTagString;
|
|
1691
1864
|
exports.getI18nText = getI18nText;
|
|
1865
|
+
exports.getSelectedNodeHierarchyStatus = getSelectedNodeHierarchyStatus;
|
|
1692
1866
|
exports.getSiblings = getSiblings;
|
|
1867
|
+
exports.getTreeAncestors = getTreeAncestors;
|
|
1868
|
+
exports.getTreeDescendants = getTreeDescendants;
|
|
1693
1869
|
exports.getTreeRelation = getTreeRelation;
|
|
1694
1870
|
exports.hasOwnProperty = hasOwnProperty;
|
|
1695
1871
|
exports.initTranslateI18nFn = initTranslateI18nFn;
|
|
1696
1872
|
exports.insert = insert;
|
|
1873
|
+
exports.isArray = isArray;
|
|
1874
|
+
exports.isBoolean = isBoolean;
|
|
1697
1875
|
exports.isEmptyObject = isEmptyObject;
|
|
1876
|
+
exports.isFunction = isFunction;
|
|
1698
1877
|
exports.isIntegerKey = isIntegerKey;
|
|
1878
|
+
exports.isNaN = isNaN;
|
|
1879
|
+
exports.isNil = isNil;
|
|
1880
|
+
exports.isNull = isNull;
|
|
1881
|
+
exports.isNumber = isNumber;
|
|
1882
|
+
exports.isObject = isObject;
|
|
1883
|
+
exports.isString = isString;
|
|
1884
|
+
exports.isUndefined = isUndefined;
|
|
1699
1885
|
exports.levelTransformTree = levelTransformTree;
|
|
1700
1886
|
exports.makeDestructurable = makeDestructurable;
|
|
1701
1887
|
exports.mergeAdjacent = mergeAdjacent;
|
package/dist/OnchainUtility.mjs
CHANGED
|
@@ -17,6 +17,7 @@ import { useRef, useState, useCallback, useLayoutEffect } from 'react';
|
|
|
17
17
|
*/
|
|
18
18
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
19
19
|
|
|
20
|
+
/** 是否是Moment对象(_表示为内部函数谨慎使用) */
|
|
20
21
|
function _isMoment(obj) {
|
|
21
22
|
return obj != null && typeof obj === 'object' &&
|
|
22
23
|
// 检查内部标志
|
|
@@ -26,6 +27,13 @@ function _isMoment(obj) {
|
|
|
26
27
|
// 检查内部属性
|
|
27
28
|
'_d' in obj && '_i' in obj;
|
|
28
29
|
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 创建一个可解构的对象,该对象同时具有原始对象的属性和数组的迭代器,使其可以使用对象和数组两种解构方式
|
|
33
|
+
* @param obj - 需要转换的对象
|
|
34
|
+
* @param arr - 用于提供迭代器的数组
|
|
35
|
+
* @returns 一个结合了对象属性和数组迭代器的新对象
|
|
36
|
+
*/
|
|
29
37
|
function makeDestructurable(obj, arr) {
|
|
30
38
|
if (typeof Symbol !== 'undefined') {
|
|
31
39
|
const clone = {
|
|
@@ -48,6 +56,8 @@ function makeDestructurable(obj, arr) {
|
|
|
48
56
|
return Object.assign([...arr], obj);
|
|
49
57
|
}
|
|
50
58
|
}
|
|
59
|
+
|
|
60
|
+
/** 创建对象枚举,可以避免两个相同枚举缺不相等 */
|
|
51
61
|
function createEnumObject(o) {
|
|
52
62
|
return o;
|
|
53
63
|
}
|
|
@@ -58,15 +68,68 @@ function toRawType(value) {
|
|
|
58
68
|
// 从字符串中提取“RawType”,如“[object RawType]”
|
|
59
69
|
return toTypeString(value).slice(8, -1);
|
|
60
70
|
}
|
|
71
|
+
function isString(value) {
|
|
72
|
+
return toRawType(value) === 'String';
|
|
73
|
+
}
|
|
74
|
+
function isNumber(value) {
|
|
75
|
+
return toRawType(value) === 'Number';
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** 判断值是否为NaN */
|
|
79
|
+
function isNaN(value) {
|
|
80
|
+
return Number.isNaN(value);
|
|
81
|
+
}
|
|
82
|
+
function isBoolean(value) {
|
|
83
|
+
return toRawType(value) === 'Boolean';
|
|
84
|
+
}
|
|
85
|
+
function isUndefined(value) {
|
|
86
|
+
return toRawType(value) === 'Undefined';
|
|
87
|
+
}
|
|
88
|
+
function isNull(value) {
|
|
89
|
+
return toRawType(value) === 'Null';
|
|
90
|
+
}
|
|
91
|
+
function isNil(value) {
|
|
92
|
+
return isNull(value) || isUndefined(value);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 判断是否是 `null` 或 `undefined`
|
|
97
|
+
* @example
|
|
98
|
+
* _.isNil(null);
|
|
99
|
+
* // => true
|
|
100
|
+
*
|
|
101
|
+
* _.isNil(void 0);
|
|
102
|
+
* // => true
|
|
103
|
+
*
|
|
104
|
+
* _.isNil(NaN);
|
|
105
|
+
* // => false
|
|
106
|
+
*/
|
|
107
|
+
function isObject(value) {
|
|
108
|
+
return toRawType(value) === 'Object';
|
|
109
|
+
}
|
|
110
|
+
function isArray(value) {
|
|
111
|
+
return toRawType(value) === 'Array';
|
|
112
|
+
}
|
|
113
|
+
function isFunction(value) {
|
|
114
|
+
return toRawType(value) === 'Function';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** 判断对象是否有某个属性 */
|
|
61
118
|
function hasOwnProperty(data, key) {
|
|
62
119
|
return data && Object.prototype.hasOwnProperty.call(data, key);
|
|
63
120
|
}
|
|
121
|
+
|
|
122
|
+
/** 是否是整型key */
|
|
64
123
|
function isIntegerKey(key) {
|
|
65
124
|
return typeof key === 'string' && key !== 'NaN' && key[0] !== '-' && '' + parseInt(key, 10) === key;
|
|
66
125
|
}
|
|
126
|
+
|
|
127
|
+
/** 是否是空对象 */
|
|
67
128
|
function isEmptyObject(obj) {
|
|
68
129
|
return obj ? !Object.keys(obj).length : true;
|
|
69
130
|
}
|
|
131
|
+
|
|
132
|
+
/** 生成 innerHTML */
|
|
70
133
|
function getHTMLTagString(params) {
|
|
71
134
|
const attrsString = Object.entries(params.attributes || {}).map(([key, value]) => {
|
|
72
135
|
return ` ${key}="${value}"`;
|
|
@@ -1080,6 +1143,46 @@ function levelTransformTree({
|
|
|
1080
1143
|
});
|
|
1081
1144
|
return root.children;
|
|
1082
1145
|
}
|
|
1146
|
+
|
|
1147
|
+
/** 获取全部子孙节点 */
|
|
1148
|
+
function getTreeDescendants({
|
|
1149
|
+
data,
|
|
1150
|
+
key,
|
|
1151
|
+
signKey = 'id',
|
|
1152
|
+
childrenKey = 'children'
|
|
1153
|
+
}) {
|
|
1154
|
+
const {
|
|
1155
|
+
self
|
|
1156
|
+
} = getTreeRelation({
|
|
1157
|
+
childrenKey,
|
|
1158
|
+
data,
|
|
1159
|
+
lookup(item, index) {
|
|
1160
|
+
return item[signKey] === key;
|
|
1161
|
+
}
|
|
1162
|
+
});
|
|
1163
|
+
return arrayAttributeFlat({
|
|
1164
|
+
childrenKey,
|
|
1165
|
+
data: self?.[childrenKey] || []
|
|
1166
|
+
});
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
/** 获取全部祖先节点 */
|
|
1170
|
+
function getTreeAncestors({
|
|
1171
|
+
data,
|
|
1172
|
+
key,
|
|
1173
|
+
signKey = 'id',
|
|
1174
|
+
childrenKey = 'children'
|
|
1175
|
+
}) {
|
|
1176
|
+
return getTreeRelation({
|
|
1177
|
+
childrenKey,
|
|
1178
|
+
data,
|
|
1179
|
+
lookup(item, index) {
|
|
1180
|
+
return item[signKey] === key;
|
|
1181
|
+
}
|
|
1182
|
+
}).stack;
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
/** 删除树节点 */
|
|
1083
1186
|
function deleteTreeNodes({
|
|
1084
1187
|
data,
|
|
1085
1188
|
selectedKeys,
|
|
@@ -1233,6 +1336,51 @@ function getSiblings({
|
|
|
1233
1336
|
return keys;
|
|
1234
1337
|
}
|
|
1235
1338
|
|
|
1339
|
+
/**
|
|
1340
|
+
* @description 是否跨层
|
|
1341
|
+
* @date 2022-11-21 20:03:52
|
|
1342
|
+
* @export
|
|
1343
|
+
* @param {string[]} hierarchy 选中任务的层级
|
|
1344
|
+
* @returns {*}
|
|
1345
|
+
*/
|
|
1346
|
+
function getSelectedNodeHierarchyStatus({
|
|
1347
|
+
data,
|
|
1348
|
+
selectedKeys,
|
|
1349
|
+
signKey = 'id',
|
|
1350
|
+
childrenKey = 'children'
|
|
1351
|
+
}) {
|
|
1352
|
+
const relations = selectedKeys.map(key => getTreeRelation({
|
|
1353
|
+
childrenKey,
|
|
1354
|
+
data,
|
|
1355
|
+
lookup(item, index) {
|
|
1356
|
+
return item[signKey] === key;
|
|
1357
|
+
}
|
|
1358
|
+
}));
|
|
1359
|
+
// 深度集合
|
|
1360
|
+
const deepSet = new Set(relations.map(rel => rel.stack.length));
|
|
1361
|
+
const isDifferentDepths = deepSet.size > 1;
|
|
1362
|
+
if (isDifferentDepths) {
|
|
1363
|
+
return {
|
|
1364
|
+
isDifferentDepths,
|
|
1365
|
+
isIncludedParent: relations.sort((a, b) => {
|
|
1366
|
+
return b.stack.length - a.stack.length;
|
|
1367
|
+
}).some(item => {
|
|
1368
|
+
const ancestors = getTreeAncestors({
|
|
1369
|
+
childrenKey,
|
|
1370
|
+
data,
|
|
1371
|
+
key: item.self[signKey],
|
|
1372
|
+
signKey
|
|
1373
|
+
}).map(item => item[signKey]);
|
|
1374
|
+
return selectedKeys.some(id => ancestors.includes(id));
|
|
1375
|
+
})
|
|
1376
|
+
};
|
|
1377
|
+
}
|
|
1378
|
+
return {
|
|
1379
|
+
isDifferentDepths,
|
|
1380
|
+
isIncludedParent: false
|
|
1381
|
+
};
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1236
1384
|
/**
|
|
1237
1385
|
* @description 合并相邻的选中数据
|
|
1238
1386
|
* @date 2023-02-15 16:11:16
|
|
@@ -1351,9 +1499,10 @@ function generatedAcrossHierarchySort({
|
|
|
1351
1499
|
function optimizeStructure({
|
|
1352
1500
|
data,
|
|
1353
1501
|
childrenKey = 'children',
|
|
1354
|
-
signKey = 'id'
|
|
1502
|
+
signKey = 'id',
|
|
1503
|
+
isSupportMultipleRoot = false
|
|
1355
1504
|
}) {
|
|
1356
|
-
if (data.length > 1) {
|
|
1505
|
+
if (data.length > 1 || isSupportMultipleRoot) {
|
|
1357
1506
|
return [{
|
|
1358
1507
|
[childrenKey]: data,
|
|
1359
1508
|
isCustom: true,
|
|
@@ -1458,6 +1607,7 @@ async function upgrade({
|
|
|
1458
1607
|
data,
|
|
1459
1608
|
signKey = 'id',
|
|
1460
1609
|
isFollow,
|
|
1610
|
+
isSupportMultipleRoot = false,
|
|
1461
1611
|
onStopFollow,
|
|
1462
1612
|
onFilterFollow,
|
|
1463
1613
|
onUpgrade,
|
|
@@ -1469,6 +1619,7 @@ async function upgrade({
|
|
|
1469
1619
|
data = optimizeStructure({
|
|
1470
1620
|
childrenKey,
|
|
1471
1621
|
data,
|
|
1622
|
+
isSupportMultipleRoot,
|
|
1472
1623
|
signKey
|
|
1473
1624
|
});
|
|
1474
1625
|
const layers = mergeAdjacent({
|
|
@@ -1554,7 +1705,12 @@ async function upgrade({
|
|
|
1554
1705
|
});
|
|
1555
1706
|
const insert = (data, index) => {
|
|
1556
1707
|
data.splice(index, 0, ...selected);
|
|
1557
|
-
onUpgraded?.(selected
|
|
1708
|
+
onUpgraded?.(selected, getExpandedState({
|
|
1709
|
+
childrenKey,
|
|
1710
|
+
originalParent: parent,
|
|
1711
|
+
parent: grandpa,
|
|
1712
|
+
signKey
|
|
1713
|
+
}));
|
|
1558
1714
|
};
|
|
1559
1715
|
const insertIndex = getInsertIdx({
|
|
1560
1716
|
leader: start,
|
|
@@ -1616,7 +1772,12 @@ async function downgrade({
|
|
|
1616
1772
|
const newChildren = [...(before[childrenKey] || []), ...children];
|
|
1617
1773
|
if (children.length) {
|
|
1618
1774
|
before[childrenKey] = [...newChildren];
|
|
1619
|
-
onDowngraded?.(children
|
|
1775
|
+
onDowngraded?.(children, getExpandedState({
|
|
1776
|
+
childrenKey,
|
|
1777
|
+
originalParent: parent,
|
|
1778
|
+
parent: before,
|
|
1779
|
+
signKey
|
|
1780
|
+
}));
|
|
1620
1781
|
}
|
|
1621
1782
|
}
|
|
1622
1783
|
}
|
|
@@ -1669,5 +1830,17 @@ function treeSearch({
|
|
|
1669
1830
|
}
|
|
1670
1831
|
}).filter(row => !!row);
|
|
1671
1832
|
}
|
|
1833
|
+
function getExpandedState({
|
|
1834
|
+
originalParent,
|
|
1835
|
+
parent,
|
|
1836
|
+
signKey = 'id',
|
|
1837
|
+
childrenKey = 'children'
|
|
1838
|
+
}) {
|
|
1839
|
+
const isRemove = !originalParent[childrenKey]?.length;
|
|
1840
|
+
return {
|
|
1841
|
+
add: parent[signKey],
|
|
1842
|
+
remove: isRemove ? originalParent[signKey] : null
|
|
1843
|
+
};
|
|
1844
|
+
}
|
|
1672
1845
|
|
|
1673
|
-
export { _isMoment, arrayAttributeFlat, asyncDfs, base64ToFile, base64ToMimeType, baseTemplate, bfs, createEnumObject, deleteTreeNodes, dfs, downgrade, fromBase64UTF8, generateSecureUUID, generatedAcrossHierarchySort, getBase64Regular, getHTMLTagString, getI18nText, getSiblings, getTreeRelation, hasOwnProperty, initTranslateI18nFn, insert, isEmptyObject, isIntegerKey, levelTransformTree, makeDestructurable, mergeAdjacent, movUp, move, moveDown, t, toBase64UTF8, toRawType, toTypeString, translateI18n, treeSearch, upgrade, useReactive, useShallowReactive, useStore };
|
|
1846
|
+
export { _isMoment, arrayAttributeFlat, asyncDfs, base64ToFile, base64ToMimeType, baseTemplate, bfs, createEnumObject, deleteTreeNodes, dfs, downgrade, fromBase64UTF8, generateSecureUUID, generatedAcrossHierarchySort, getBase64Regular, getHTMLTagString, getI18nText, getSelectedNodeHierarchyStatus, getSiblings, getTreeAncestors, getTreeDescendants, getTreeRelation, hasOwnProperty, initTranslateI18nFn, insert, isArray, isBoolean, isEmptyObject, isFunction, isIntegerKey, isNaN, isNil, isNull, isNumber, isObject, isString, isUndefined, levelTransformTree, makeDestructurable, mergeAdjacent, movUp, move, moveDown, t, toBase64UTF8, toRawType, toTypeString, translateI18n, treeSearch, upgrade, useReactive, useShallowReactive, useStore };
|
package/dist/Tree.js
CHANGED
|
@@ -61,6 +61,46 @@ function levelTransformTree({
|
|
|
61
61
|
});
|
|
62
62
|
return root.children;
|
|
63
63
|
}
|
|
64
|
+
|
|
65
|
+
/** 获取全部子孙节点 */
|
|
66
|
+
function getTreeDescendants({
|
|
67
|
+
data,
|
|
68
|
+
key,
|
|
69
|
+
signKey = 'id',
|
|
70
|
+
childrenKey = 'children'
|
|
71
|
+
}) {
|
|
72
|
+
const {
|
|
73
|
+
self
|
|
74
|
+
} = getTreeRelation({
|
|
75
|
+
childrenKey,
|
|
76
|
+
data,
|
|
77
|
+
lookup(item, index) {
|
|
78
|
+
return item[signKey] === key;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return arrayAttributeFlat({
|
|
82
|
+
childrenKey,
|
|
83
|
+
data: self?.[childrenKey] || []
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** 获取全部祖先节点 */
|
|
88
|
+
function getTreeAncestors({
|
|
89
|
+
data,
|
|
90
|
+
key,
|
|
91
|
+
signKey = 'id',
|
|
92
|
+
childrenKey = 'children'
|
|
93
|
+
}) {
|
|
94
|
+
return getTreeRelation({
|
|
95
|
+
childrenKey,
|
|
96
|
+
data,
|
|
97
|
+
lookup(item, index) {
|
|
98
|
+
return item[signKey] === key;
|
|
99
|
+
}
|
|
100
|
+
}).stack;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** 删除树节点 */
|
|
64
104
|
function deleteTreeNodes({
|
|
65
105
|
data,
|
|
66
106
|
selectedKeys,
|
|
@@ -214,6 +254,51 @@ function getSiblings({
|
|
|
214
254
|
return keys;
|
|
215
255
|
}
|
|
216
256
|
|
|
257
|
+
/**
|
|
258
|
+
* @description 是否跨层
|
|
259
|
+
* @date 2022-11-21 20:03:52
|
|
260
|
+
* @export
|
|
261
|
+
* @param {string[]} hierarchy 选中任务的层级
|
|
262
|
+
* @returns {*}
|
|
263
|
+
*/
|
|
264
|
+
function getSelectedNodeHierarchyStatus({
|
|
265
|
+
data,
|
|
266
|
+
selectedKeys,
|
|
267
|
+
signKey = 'id',
|
|
268
|
+
childrenKey = 'children'
|
|
269
|
+
}) {
|
|
270
|
+
const relations = selectedKeys.map(key => getTreeRelation({
|
|
271
|
+
childrenKey,
|
|
272
|
+
data,
|
|
273
|
+
lookup(item, index) {
|
|
274
|
+
return item[signKey] === key;
|
|
275
|
+
}
|
|
276
|
+
}));
|
|
277
|
+
// 深度集合
|
|
278
|
+
const deepSet = new Set(relations.map(rel => rel.stack.length));
|
|
279
|
+
const isDifferentDepths = deepSet.size > 1;
|
|
280
|
+
if (isDifferentDepths) {
|
|
281
|
+
return {
|
|
282
|
+
isDifferentDepths,
|
|
283
|
+
isIncludedParent: relations.sort((a, b) => {
|
|
284
|
+
return b.stack.length - a.stack.length;
|
|
285
|
+
}).some(item => {
|
|
286
|
+
const ancestors = getTreeAncestors({
|
|
287
|
+
childrenKey,
|
|
288
|
+
data,
|
|
289
|
+
key: item.self[signKey],
|
|
290
|
+
signKey
|
|
291
|
+
}).map(item => item[signKey]);
|
|
292
|
+
return selectedKeys.some(id => ancestors.includes(id));
|
|
293
|
+
})
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
return {
|
|
297
|
+
isDifferentDepths,
|
|
298
|
+
isIncludedParent: false
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
217
302
|
/**
|
|
218
303
|
* @description 合并相邻的选中数据
|
|
219
304
|
* @date 2023-02-15 16:11:16
|
|
@@ -332,9 +417,10 @@ function generatedAcrossHierarchySort({
|
|
|
332
417
|
function optimizeStructure({
|
|
333
418
|
data,
|
|
334
419
|
childrenKey = 'children',
|
|
335
|
-
signKey = 'id'
|
|
420
|
+
signKey = 'id',
|
|
421
|
+
isSupportMultipleRoot = false
|
|
336
422
|
}) {
|
|
337
|
-
if (data.length > 1) {
|
|
423
|
+
if (data.length > 1 || isSupportMultipleRoot) {
|
|
338
424
|
return [{
|
|
339
425
|
[childrenKey]: data,
|
|
340
426
|
isCustom: true,
|
|
@@ -439,6 +525,7 @@ async function upgrade({
|
|
|
439
525
|
data,
|
|
440
526
|
signKey = 'id',
|
|
441
527
|
isFollow,
|
|
528
|
+
isSupportMultipleRoot = false,
|
|
442
529
|
onStopFollow,
|
|
443
530
|
onFilterFollow,
|
|
444
531
|
onUpgrade,
|
|
@@ -450,6 +537,7 @@ async function upgrade({
|
|
|
450
537
|
data = optimizeStructure({
|
|
451
538
|
childrenKey,
|
|
452
539
|
data,
|
|
540
|
+
isSupportMultipleRoot,
|
|
453
541
|
signKey
|
|
454
542
|
});
|
|
455
543
|
const layers = mergeAdjacent({
|
|
@@ -535,7 +623,12 @@ async function upgrade({
|
|
|
535
623
|
});
|
|
536
624
|
const insert = (data, index) => {
|
|
537
625
|
data.splice(index, 0, ...selected);
|
|
538
|
-
onUpgraded?.(selected
|
|
626
|
+
onUpgraded?.(selected, getExpandedState({
|
|
627
|
+
childrenKey,
|
|
628
|
+
originalParent: parent,
|
|
629
|
+
parent: grandpa,
|
|
630
|
+
signKey
|
|
631
|
+
}));
|
|
539
632
|
};
|
|
540
633
|
const insertIndex = getInsertIdx({
|
|
541
634
|
leader: start,
|
|
@@ -597,7 +690,12 @@ async function downgrade({
|
|
|
597
690
|
const newChildren = [...(before[childrenKey] || []), ...children];
|
|
598
691
|
if (children.length) {
|
|
599
692
|
before[childrenKey] = [...newChildren];
|
|
600
|
-
onDowngraded?.(children
|
|
693
|
+
onDowngraded?.(children, getExpandedState({
|
|
694
|
+
childrenKey,
|
|
695
|
+
originalParent: parent,
|
|
696
|
+
parent: before,
|
|
697
|
+
signKey
|
|
698
|
+
}));
|
|
601
699
|
}
|
|
602
700
|
}
|
|
603
701
|
}
|
|
@@ -650,12 +748,27 @@ function treeSearch({
|
|
|
650
748
|
}
|
|
651
749
|
}).filter(row => !!row);
|
|
652
750
|
}
|
|
751
|
+
function getExpandedState({
|
|
752
|
+
originalParent,
|
|
753
|
+
parent,
|
|
754
|
+
signKey = 'id',
|
|
755
|
+
childrenKey = 'children'
|
|
756
|
+
}) {
|
|
757
|
+
const isRemove = !originalParent[childrenKey]?.length;
|
|
758
|
+
return {
|
|
759
|
+
add: parent[signKey],
|
|
760
|
+
remove: isRemove ? originalParent[signKey] : null
|
|
761
|
+
};
|
|
762
|
+
}
|
|
653
763
|
|
|
654
764
|
exports.arrayAttributeFlat = arrayAttributeFlat;
|
|
655
765
|
exports.deleteTreeNodes = deleteTreeNodes;
|
|
656
766
|
exports.downgrade = downgrade;
|
|
657
767
|
exports.generatedAcrossHierarchySort = generatedAcrossHierarchySort;
|
|
768
|
+
exports.getSelectedNodeHierarchyStatus = getSelectedNodeHierarchyStatus;
|
|
658
769
|
exports.getSiblings = getSiblings;
|
|
770
|
+
exports.getTreeAncestors = getTreeAncestors;
|
|
771
|
+
exports.getTreeDescendants = getTreeDescendants;
|
|
659
772
|
exports.getTreeRelation = getTreeRelation;
|
|
660
773
|
exports.insert = insert;
|
|
661
774
|
exports.levelTransformTree = levelTransformTree;
|
package/dist/Tree.mjs
CHANGED
|
@@ -59,6 +59,46 @@ function levelTransformTree({
|
|
|
59
59
|
});
|
|
60
60
|
return root.children;
|
|
61
61
|
}
|
|
62
|
+
|
|
63
|
+
/** 获取全部子孙节点 */
|
|
64
|
+
function getTreeDescendants({
|
|
65
|
+
data,
|
|
66
|
+
key,
|
|
67
|
+
signKey = 'id',
|
|
68
|
+
childrenKey = 'children'
|
|
69
|
+
}) {
|
|
70
|
+
const {
|
|
71
|
+
self
|
|
72
|
+
} = getTreeRelation({
|
|
73
|
+
childrenKey,
|
|
74
|
+
data,
|
|
75
|
+
lookup(item, index) {
|
|
76
|
+
return item[signKey] === key;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
return arrayAttributeFlat({
|
|
80
|
+
childrenKey,
|
|
81
|
+
data: self?.[childrenKey] || []
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** 获取全部祖先节点 */
|
|
86
|
+
function getTreeAncestors({
|
|
87
|
+
data,
|
|
88
|
+
key,
|
|
89
|
+
signKey = 'id',
|
|
90
|
+
childrenKey = 'children'
|
|
91
|
+
}) {
|
|
92
|
+
return getTreeRelation({
|
|
93
|
+
childrenKey,
|
|
94
|
+
data,
|
|
95
|
+
lookup(item, index) {
|
|
96
|
+
return item[signKey] === key;
|
|
97
|
+
}
|
|
98
|
+
}).stack;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** 删除树节点 */
|
|
62
102
|
function deleteTreeNodes({
|
|
63
103
|
data,
|
|
64
104
|
selectedKeys,
|
|
@@ -212,6 +252,51 @@ function getSiblings({
|
|
|
212
252
|
return keys;
|
|
213
253
|
}
|
|
214
254
|
|
|
255
|
+
/**
|
|
256
|
+
* @description 是否跨层
|
|
257
|
+
* @date 2022-11-21 20:03:52
|
|
258
|
+
* @export
|
|
259
|
+
* @param {string[]} hierarchy 选中任务的层级
|
|
260
|
+
* @returns {*}
|
|
261
|
+
*/
|
|
262
|
+
function getSelectedNodeHierarchyStatus({
|
|
263
|
+
data,
|
|
264
|
+
selectedKeys,
|
|
265
|
+
signKey = 'id',
|
|
266
|
+
childrenKey = 'children'
|
|
267
|
+
}) {
|
|
268
|
+
const relations = selectedKeys.map(key => getTreeRelation({
|
|
269
|
+
childrenKey,
|
|
270
|
+
data,
|
|
271
|
+
lookup(item, index) {
|
|
272
|
+
return item[signKey] === key;
|
|
273
|
+
}
|
|
274
|
+
}));
|
|
275
|
+
// 深度集合
|
|
276
|
+
const deepSet = new Set(relations.map(rel => rel.stack.length));
|
|
277
|
+
const isDifferentDepths = deepSet.size > 1;
|
|
278
|
+
if (isDifferentDepths) {
|
|
279
|
+
return {
|
|
280
|
+
isDifferentDepths,
|
|
281
|
+
isIncludedParent: relations.sort((a, b) => {
|
|
282
|
+
return b.stack.length - a.stack.length;
|
|
283
|
+
}).some(item => {
|
|
284
|
+
const ancestors = getTreeAncestors({
|
|
285
|
+
childrenKey,
|
|
286
|
+
data,
|
|
287
|
+
key: item.self[signKey],
|
|
288
|
+
signKey
|
|
289
|
+
}).map(item => item[signKey]);
|
|
290
|
+
return selectedKeys.some(id => ancestors.includes(id));
|
|
291
|
+
})
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
isDifferentDepths,
|
|
296
|
+
isIncludedParent: false
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
215
300
|
/**
|
|
216
301
|
* @description 合并相邻的选中数据
|
|
217
302
|
* @date 2023-02-15 16:11:16
|
|
@@ -330,9 +415,10 @@ function generatedAcrossHierarchySort({
|
|
|
330
415
|
function optimizeStructure({
|
|
331
416
|
data,
|
|
332
417
|
childrenKey = 'children',
|
|
333
|
-
signKey = 'id'
|
|
418
|
+
signKey = 'id',
|
|
419
|
+
isSupportMultipleRoot = false
|
|
334
420
|
}) {
|
|
335
|
-
if (data.length > 1) {
|
|
421
|
+
if (data.length > 1 || isSupportMultipleRoot) {
|
|
336
422
|
return [{
|
|
337
423
|
[childrenKey]: data,
|
|
338
424
|
isCustom: true,
|
|
@@ -437,6 +523,7 @@ async function upgrade({
|
|
|
437
523
|
data,
|
|
438
524
|
signKey = 'id',
|
|
439
525
|
isFollow,
|
|
526
|
+
isSupportMultipleRoot = false,
|
|
440
527
|
onStopFollow,
|
|
441
528
|
onFilterFollow,
|
|
442
529
|
onUpgrade,
|
|
@@ -448,6 +535,7 @@ async function upgrade({
|
|
|
448
535
|
data = optimizeStructure({
|
|
449
536
|
childrenKey,
|
|
450
537
|
data,
|
|
538
|
+
isSupportMultipleRoot,
|
|
451
539
|
signKey
|
|
452
540
|
});
|
|
453
541
|
const layers = mergeAdjacent({
|
|
@@ -533,7 +621,12 @@ async function upgrade({
|
|
|
533
621
|
});
|
|
534
622
|
const insert = (data, index) => {
|
|
535
623
|
data.splice(index, 0, ...selected);
|
|
536
|
-
onUpgraded?.(selected
|
|
624
|
+
onUpgraded?.(selected, getExpandedState({
|
|
625
|
+
childrenKey,
|
|
626
|
+
originalParent: parent,
|
|
627
|
+
parent: grandpa,
|
|
628
|
+
signKey
|
|
629
|
+
}));
|
|
537
630
|
};
|
|
538
631
|
const insertIndex = getInsertIdx({
|
|
539
632
|
leader: start,
|
|
@@ -595,7 +688,12 @@ async function downgrade({
|
|
|
595
688
|
const newChildren = [...(before[childrenKey] || []), ...children];
|
|
596
689
|
if (children.length) {
|
|
597
690
|
before[childrenKey] = [...newChildren];
|
|
598
|
-
onDowngraded?.(children
|
|
691
|
+
onDowngraded?.(children, getExpandedState({
|
|
692
|
+
childrenKey,
|
|
693
|
+
originalParent: parent,
|
|
694
|
+
parent: before,
|
|
695
|
+
signKey
|
|
696
|
+
}));
|
|
599
697
|
}
|
|
600
698
|
}
|
|
601
699
|
}
|
|
@@ -648,5 +746,17 @@ function treeSearch({
|
|
|
648
746
|
}
|
|
649
747
|
}).filter(row => !!row);
|
|
650
748
|
}
|
|
749
|
+
function getExpandedState({
|
|
750
|
+
originalParent,
|
|
751
|
+
parent,
|
|
752
|
+
signKey = 'id',
|
|
753
|
+
childrenKey = 'children'
|
|
754
|
+
}) {
|
|
755
|
+
const isRemove = !originalParent[childrenKey]?.length;
|
|
756
|
+
return {
|
|
757
|
+
add: parent[signKey],
|
|
758
|
+
remove: isRemove ? originalParent[signKey] : null
|
|
759
|
+
};
|
|
760
|
+
}
|
|
651
761
|
|
|
652
|
-
export { arrayAttributeFlat, deleteTreeNodes, downgrade, generatedAcrossHierarchySort, getSiblings, getTreeRelation, insert, levelTransformTree, mergeAdjacent, movUp, move, moveDown, treeSearch, upgrade };
|
|
762
|
+
export { arrayAttributeFlat, deleteTreeNodes, downgrade, generatedAcrossHierarchySort, getSelectedNodeHierarchyStatus, getSiblings, getTreeAncestors, getTreeDescendants, getTreeRelation, insert, levelTransformTree, mergeAdjacent, movUp, move, moveDown, treeSearch, upgrade };
|
package/package.json
CHANGED
package/src/Tree/index.ts
CHANGED
|
@@ -79,9 +79,44 @@ export function levelTransformTree<T extends Item>({
|
|
|
79
79
|
}
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
type _Item = T & {children: _Item[]};
|
|
83
|
+
return root.children as _Item[];
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
/** 获取全部子孙节点 */
|
|
87
|
+
export function getTreeDescendants<T extends Item>({
|
|
88
|
+
data,
|
|
89
|
+
key,
|
|
90
|
+
signKey = 'id',
|
|
91
|
+
childrenKey = 'children',
|
|
92
|
+
}: Params<T> & {key: string}) {
|
|
93
|
+
const {self} = getTreeRelation({
|
|
94
|
+
childrenKey,
|
|
95
|
+
data,
|
|
96
|
+
lookup(item, index) {
|
|
97
|
+
return item[signKey] === key;
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
return arrayAttributeFlat({childrenKey, data: self?.[childrenKey] || []});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** 获取全部祖先节点 */
|
|
104
|
+
export function getTreeAncestors<T extends Item>({
|
|
105
|
+
data,
|
|
106
|
+
key,
|
|
107
|
+
signKey = 'id',
|
|
108
|
+
childrenKey = 'children',
|
|
109
|
+
}: Params<T> & {key: string}) {
|
|
110
|
+
return getTreeRelation({
|
|
111
|
+
childrenKey,
|
|
112
|
+
data,
|
|
113
|
+
lookup(item, index) {
|
|
114
|
+
return item[signKey] === key;
|
|
115
|
+
},
|
|
116
|
+
}).stack;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** 删除树节点 */
|
|
85
120
|
export function deleteTreeNodes<T extends Item>({
|
|
86
121
|
data,
|
|
87
122
|
selectedKeys,
|
|
@@ -264,6 +299,63 @@ export function getSiblings<T extends Item>({
|
|
|
264
299
|
return keys;
|
|
265
300
|
}
|
|
266
301
|
|
|
302
|
+
/**
|
|
303
|
+
* @description 是否跨层
|
|
304
|
+
* @date 2022-11-21 20:03:52
|
|
305
|
+
* @export
|
|
306
|
+
* @param {string[]} hierarchy 选中任务的层级
|
|
307
|
+
* @returns {*}
|
|
308
|
+
*/
|
|
309
|
+
export function getSelectedNodeHierarchyStatus<T extends Item>({
|
|
310
|
+
data,
|
|
311
|
+
selectedKeys,
|
|
312
|
+
signKey = 'id',
|
|
313
|
+
childrenKey = 'children',
|
|
314
|
+
}: Params<T> & {
|
|
315
|
+
selectedKeys: string[];
|
|
316
|
+
}): {
|
|
317
|
+
/** 层级深度是否有差别 */
|
|
318
|
+
isDifferentDepths: boolean;
|
|
319
|
+
/** 选中是否包含了祖先节点和其后的节点 */
|
|
320
|
+
isIncludedParent: boolean;
|
|
321
|
+
} {
|
|
322
|
+
const relations = selectedKeys.map((key) =>
|
|
323
|
+
getTreeRelation({
|
|
324
|
+
childrenKey,
|
|
325
|
+
data,
|
|
326
|
+
lookup(item, index) {
|
|
327
|
+
return item[signKey] === key;
|
|
328
|
+
},
|
|
329
|
+
}),
|
|
330
|
+
);
|
|
331
|
+
// 深度集合
|
|
332
|
+
const deepSet = new Set(relations.map((rel) => rel.stack.length));
|
|
333
|
+
const isDifferentDepths = deepSet.size > 1;
|
|
334
|
+
if (isDifferentDepths) {
|
|
335
|
+
return {
|
|
336
|
+
isDifferentDepths,
|
|
337
|
+
isIncludedParent: relations
|
|
338
|
+
.sort((a, b) => {
|
|
339
|
+
return b.stack.length - a.stack.length;
|
|
340
|
+
})
|
|
341
|
+
.some((item) => {
|
|
342
|
+
const ancestors = getTreeAncestors({
|
|
343
|
+
childrenKey,
|
|
344
|
+
data,
|
|
345
|
+
key: item.self[signKey],
|
|
346
|
+
signKey,
|
|
347
|
+
}).map((item) => item[signKey]);
|
|
348
|
+
return selectedKeys.some((id) => ancestors.includes(id));
|
|
349
|
+
}),
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return {
|
|
354
|
+
isDifferentDepths,
|
|
355
|
+
isIncludedParent: false,
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
|
|
267
359
|
/**
|
|
268
360
|
* @description 合并相邻的选中数据
|
|
269
361
|
* @date 2023-02-15 16:11:16
|
|
@@ -399,8 +491,9 @@ function optimizeStructure<T>({
|
|
|
399
491
|
data,
|
|
400
492
|
childrenKey = 'children',
|
|
401
493
|
signKey = 'id',
|
|
402
|
-
|
|
403
|
-
|
|
494
|
+
isSupportMultipleRoot = false,
|
|
495
|
+
}: Params<T> & {isSupportMultipleRoot?: boolean}): T[] {
|
|
496
|
+
if (data.length > 1 || isSupportMultipleRoot) {
|
|
404
497
|
return [
|
|
405
498
|
{
|
|
406
499
|
[childrenKey]: data,
|
|
@@ -437,6 +530,16 @@ type MoveParams<T> = Params<T> & {
|
|
|
437
530
|
onError?: (params: {selected: T[]; isMoveUp?: boolean}) => boolean | void;
|
|
438
531
|
};
|
|
439
532
|
|
|
533
|
+
interface ParentParams<T> {
|
|
534
|
+
originalParent: T;
|
|
535
|
+
parent: T;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
interface ExpandedState<T> {
|
|
539
|
+
add: T;
|
|
540
|
+
remove: T | null;
|
|
541
|
+
}
|
|
542
|
+
|
|
440
543
|
export function move<T extends Item>({
|
|
441
544
|
data,
|
|
442
545
|
signKey = 'id',
|
|
@@ -508,10 +611,17 @@ export function moveDown<T extends Item>(_: MoveParams<T>) {
|
|
|
508
611
|
});
|
|
509
612
|
}
|
|
510
613
|
|
|
614
|
+
interface OnUpgradeParams<T> {
|
|
615
|
+
selected: T[];
|
|
616
|
+
parent: T;
|
|
617
|
+
grandpa?: T;
|
|
618
|
+
}
|
|
619
|
+
|
|
511
620
|
export async function upgrade<T extends Item>({
|
|
512
621
|
data,
|
|
513
622
|
signKey = 'id',
|
|
514
623
|
isFollow,
|
|
624
|
+
isSupportMultipleRoot = false,
|
|
515
625
|
onStopFollow,
|
|
516
626
|
onFilterFollow,
|
|
517
627
|
onUpgrade,
|
|
@@ -521,16 +631,16 @@ export async function upgrade<T extends Item>({
|
|
|
521
631
|
onError,
|
|
522
632
|
}: MoveParams<T> & {
|
|
523
633
|
isFollow?: boolean;
|
|
634
|
+
isSupportMultipleRoot?: boolean;
|
|
524
635
|
onStopFollow?: (item: T) => boolean;
|
|
525
636
|
onFilterFollow?: (item: T[]) => T[];
|
|
526
|
-
onUpgrade?: (params:
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
onUpgraded?: (upgrades: T[]) => void;
|
|
637
|
+
onUpgrade?: (params: OnUpgradeParams<T>) => Promise<boolean> | boolean;
|
|
638
|
+
onUpgraded?: (
|
|
639
|
+
upgrades: T[],
|
|
640
|
+
params: ExpandedState<T[typeof signKey]>,
|
|
641
|
+
) => void;
|
|
532
642
|
}) {
|
|
533
|
-
data = optimizeStructure({childrenKey, data, signKey});
|
|
643
|
+
data = optimizeStructure({childrenKey, data, isSupportMultipleRoot, signKey});
|
|
534
644
|
const layers = mergeAdjacent({childrenKey, data, selectKeys, signKey});
|
|
535
645
|
const {crossLayerSort, getInsertIdx} = generatedAcrossHierarchySort({
|
|
536
646
|
signKey,
|
|
@@ -603,7 +713,16 @@ export async function upgrade<T extends Item>({
|
|
|
603
713
|
|
|
604
714
|
const insert = (data: T[], index: number) => {
|
|
605
715
|
data.splice(index, 0, ...selected);
|
|
606
|
-
onUpgraded?.(
|
|
716
|
+
onUpgraded?.(
|
|
717
|
+
selected,
|
|
718
|
+
getExpandedState({
|
|
719
|
+
childrenKey,
|
|
720
|
+
data,
|
|
721
|
+
originalParent: parent,
|
|
722
|
+
parent: grandpa!,
|
|
723
|
+
signKey,
|
|
724
|
+
}),
|
|
725
|
+
);
|
|
607
726
|
};
|
|
608
727
|
const insertIndex = getInsertIdx({
|
|
609
728
|
leader: start,
|
|
@@ -616,6 +735,12 @@ export async function upgrade<T extends Item>({
|
|
|
616
735
|
}
|
|
617
736
|
}
|
|
618
737
|
|
|
738
|
+
interface OnDowngradedParams<T> {
|
|
739
|
+
selected: T[];
|
|
740
|
+
beforeSibling: T[];
|
|
741
|
+
parent: T | undefined;
|
|
742
|
+
}
|
|
743
|
+
|
|
619
744
|
export async function downgrade<T extends Item>({
|
|
620
745
|
data,
|
|
621
746
|
signKey = 'id',
|
|
@@ -625,12 +750,11 @@ export async function downgrade<T extends Item>({
|
|
|
625
750
|
childrenKey = 'children',
|
|
626
751
|
onError,
|
|
627
752
|
}: MoveParams<T> & {
|
|
628
|
-
onDowngrade?: (params:
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
onDowngraded?: (downgrades: T[]) => void;
|
|
753
|
+
onDowngrade?: (params: OnDowngradedParams<T>) => Promise<boolean> | boolean;
|
|
754
|
+
onDowngraded?: (
|
|
755
|
+
downgrades: T[],
|
|
756
|
+
params: ExpandedState<T[typeof signKey]>,
|
|
757
|
+
) => void;
|
|
634
758
|
}) {
|
|
635
759
|
data = optimizeStructure({childrenKey, data, signKey});
|
|
636
760
|
const layers = mergeAdjacent({childrenKey, data, selectKeys, signKey});
|
|
@@ -659,7 +783,16 @@ export async function downgrade<T extends Item>({
|
|
|
659
783
|
const newChildren = [...(before[childrenKey] || []), ...children];
|
|
660
784
|
if (children.length) {
|
|
661
785
|
(before as Item)[childrenKey] = [...newChildren];
|
|
662
|
-
onDowngraded?.(
|
|
786
|
+
onDowngraded?.(
|
|
787
|
+
children,
|
|
788
|
+
getExpandedState({
|
|
789
|
+
childrenKey,
|
|
790
|
+
data,
|
|
791
|
+
originalParent: parent,
|
|
792
|
+
parent: before,
|
|
793
|
+
signKey,
|
|
794
|
+
}),
|
|
795
|
+
);
|
|
663
796
|
}
|
|
664
797
|
}
|
|
665
798
|
}
|
|
@@ -719,3 +852,19 @@ export function treeSearch<T extends Record<string, any>>({
|
|
|
719
852
|
})
|
|
720
853
|
.filter((row): row is T => !!row);
|
|
721
854
|
}
|
|
855
|
+
|
|
856
|
+
function getExpandedState<T extends Item>({
|
|
857
|
+
originalParent,
|
|
858
|
+
parent,
|
|
859
|
+
signKey = 'id',
|
|
860
|
+
childrenKey = 'children',
|
|
861
|
+
}: ParentParams<T> & Params<T>) {
|
|
862
|
+
const isRemove = !originalParent[childrenKey]?.length;
|
|
863
|
+
|
|
864
|
+
type Key = T[typeof signKey];
|
|
865
|
+
|
|
866
|
+
return {
|
|
867
|
+
add: parent[signKey] as Key,
|
|
868
|
+
remove: isRemove ? (originalParent[signKey] as Key) : null,
|
|
869
|
+
};
|
|
870
|
+
}
|
package/src/base.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
9
9
|
|
|
10
|
+
/** 是否是Moment对象(_表示为内部函数谨慎使用) */
|
|
10
11
|
export function _isMoment(obj: any) {
|
|
11
12
|
return (
|
|
12
13
|
obj != null &&
|
|
@@ -22,6 +23,12 @@ export function _isMoment(obj: any) {
|
|
|
22
23
|
);
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
/**
|
|
27
|
+
* 创建一个可解构的对象,该对象同时具有原始对象的属性和数组的迭代器,使其可以使用对象和数组两种解构方式
|
|
28
|
+
* @param obj - 需要转换的对象
|
|
29
|
+
* @param arr - 用于提供迭代器的数组
|
|
30
|
+
* @returns 一个结合了对象属性和数组迭代器的新对象
|
|
31
|
+
*/
|
|
25
32
|
export function makeDestructurable<
|
|
26
33
|
T extends Record<string, unknown>,
|
|
27
34
|
A extends readonly [any, ...any],
|
|
@@ -47,6 +54,7 @@ export function makeDestructurable<
|
|
|
47
54
|
}
|
|
48
55
|
}
|
|
49
56
|
|
|
57
|
+
/** 创建对象枚举,可以避免两个相同枚举缺不相等 */
|
|
50
58
|
export function createEnumObject<T extends string>(o: {[P in T]: P}) {
|
|
51
59
|
return o;
|
|
52
60
|
}
|
|
@@ -54,14 +62,71 @@ export function createEnumObject<T extends string>(o: {[P in T]: P}) {
|
|
|
54
62
|
export function toTypeString<T>(value: T): string {
|
|
55
63
|
return Object.prototype.toString.call(value);
|
|
56
64
|
}
|
|
65
|
+
|
|
57
66
|
export function toRawType<T>(value: T): string {
|
|
58
67
|
// 从字符串中提取“RawType”,如“[object RawType]”
|
|
59
68
|
return toTypeString(value).slice(8, -1);
|
|
60
69
|
}
|
|
70
|
+
|
|
71
|
+
export function isString(value: any): value is string {
|
|
72
|
+
return toRawType(value) === 'String';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function isNumber(value: any): value is number {
|
|
76
|
+
return toRawType(value) === 'Number';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** 判断值是否为NaN */
|
|
80
|
+
export function isNaN(value?: any): value is number {
|
|
81
|
+
return Number.isNaN(value);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function isBoolean(value?: any): value is boolean {
|
|
85
|
+
return toRawType(value) === 'Boolean';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function isUndefined(value?: any): value is undefined {
|
|
89
|
+
return toRawType(value) === 'Undefined';
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function isNull(value?: any): value is null {
|
|
93
|
+
return toRawType(value) === 'Null';
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function isNil(value?: any): value is null | undefined {
|
|
97
|
+
return isNull(value) || isUndefined(value);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 判断是否是 `null` 或 `undefined`
|
|
102
|
+
* @example
|
|
103
|
+
* _.isNil(null);
|
|
104
|
+
* // => true
|
|
105
|
+
*
|
|
106
|
+
* _.isNil(void 0);
|
|
107
|
+
* // => true
|
|
108
|
+
*
|
|
109
|
+
* _.isNil(NaN);
|
|
110
|
+
* // => false
|
|
111
|
+
*/
|
|
112
|
+
export function isObject(value?: any): value is object {
|
|
113
|
+
return toRawType(value) === 'Object';
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function isArray(value?: unknown): value is unknown[] {
|
|
117
|
+
return toRawType(value) === 'Array';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function isFunction(value?: any): value is (...args: any[]) => any {
|
|
121
|
+
return toRawType(value) === 'Function';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** 判断对象是否有某个属性 */
|
|
61
125
|
export function hasOwnProperty<T>(data: T, key: string | symbol | number) {
|
|
62
126
|
return data && Object.prototype.hasOwnProperty.call(data, key);
|
|
63
127
|
}
|
|
64
128
|
|
|
129
|
+
/** 是否是整型key */
|
|
65
130
|
export function isIntegerKey(key: unknown) {
|
|
66
131
|
return (
|
|
67
132
|
typeof key === 'string' &&
|
|
@@ -70,10 +135,13 @@ export function isIntegerKey(key: unknown) {
|
|
|
70
135
|
'' + parseInt(key, 10) === key
|
|
71
136
|
);
|
|
72
137
|
}
|
|
138
|
+
|
|
139
|
+
/** 是否是空对象 */
|
|
73
140
|
export function isEmptyObject(obj: object | undefined | null) {
|
|
74
141
|
return obj ? !Object.keys(obj).length : true;
|
|
75
142
|
}
|
|
76
143
|
|
|
144
|
+
/** 生成 innerHTML */
|
|
77
145
|
export function getHTMLTagString(params: {
|
|
78
146
|
type: string;
|
|
79
147
|
attributes?: Record<string, any>;
|