a2bei4-utils 1.0.9 → 1.0.11
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/a2bei4.utils.cjs.js +193 -2
- package/dist/a2bei4.utils.cjs.js.map +1 -1
- package/dist/a2bei4.utils.cjs.min.js +1 -1
- package/dist/a2bei4.utils.cjs.min.js.map +1 -1
- package/dist/a2bei4.utils.esm.js +191 -2
- package/dist/a2bei4.utils.esm.js.map +1 -1
- package/dist/a2bei4.utils.esm.min.js +1 -1
- package/dist/a2bei4.utils.esm.min.js.map +1 -1
- package/dist/a2bei4.utils.umd.js +193 -2
- package/dist/a2bei4.utils.umd.js.map +1 -1
- package/dist/a2bei4.utils.umd.min.js +1 -1
- package/dist/a2bei4.utils.umd.min.js.map +1 -1
- package/dist/arr.cjs.map +1 -1
- package/dist/arr.js.map +1 -1
- package/dist/audio.cjs.map +1 -1
- package/dist/audio.js.map +1 -1
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.js.map +1 -1
- package/dist/common.cjs.map +1 -1
- package/dist/common.js.map +1 -1
- package/dist/date.cjs.map +1 -1
- package/dist/date.js.map +1 -1
- package/dist/download.cjs.map +1 -1
- package/dist/download.js.map +1 -1
- package/dist/evt.cjs.map +1 -1
- package/dist/evt.js.map +1 -1
- package/dist/id.cjs.map +1 -1
- package/dist/id.js.map +1 -1
- package/dist/menu.cjs.map +1 -1
- package/dist/menu.js.map +1 -1
- package/dist/timer.cjs +14 -0
- package/dist/timer.cjs.map +1 -1
- package/dist/timer.js +14 -0
- package/dist/timer.js.map +1 -1
- package/dist/tree.cjs +177 -0
- package/dist/tree.cjs.map +1 -1
- package/dist/tree.js +176 -1
- package/dist/tree.js.map +1 -1
- package/dist/webSocket.cjs.map +1 -1
- package/dist/webSocket.js.map +1 -1
- package/package.json +5 -5
- package/types/index.d.ts +186 -2
- package/types/timer.d.ts +4 -0
- package/types/tree.d.ts +182 -1
package/dist/a2bei4.utils.umd.js
CHANGED
|
@@ -568,7 +568,7 @@ registerProcessor('audio-stream-resampler-processor', AudioStreamResamplerProces
|
|
|
568
568
|
* @param {*} obj - 待检测的值
|
|
569
569
|
* @returns {obj is string}
|
|
570
570
|
*/
|
|
571
|
-
function isNonEmptyString(obj) {
|
|
571
|
+
function isNonEmptyString$1(obj) {
|
|
572
572
|
return getDataType(obj) === "string" && obj.length > 0;
|
|
573
573
|
}
|
|
574
574
|
|
|
@@ -1827,6 +1827,10 @@ registerProcessor('audio-stream-resampler-processor', AudioStreamResamplerProces
|
|
|
1827
1827
|
this._fn = fn;
|
|
1828
1828
|
this._ms = ms;
|
|
1829
1829
|
this._timerId = null;
|
|
1830
|
+
/**
|
|
1831
|
+
* @type {symbol | null}
|
|
1832
|
+
*/
|
|
1833
|
+
this._loopId = null;
|
|
1830
1834
|
}
|
|
1831
1835
|
|
|
1832
1836
|
/**
|
|
@@ -1835,8 +1839,17 @@ registerProcessor('audio-stream-resampler-processor', AudioStreamResamplerProces
|
|
|
1835
1839
|
*/
|
|
1836
1840
|
start() {
|
|
1837
1841
|
this.stop();
|
|
1842
|
+
|
|
1843
|
+
const curLoopId = Symbol();
|
|
1844
|
+
this._loopId = curLoopId;
|
|
1845
|
+
|
|
1838
1846
|
const loop = () => {
|
|
1847
|
+
if (this._loopId !== curLoopId) return;
|
|
1848
|
+
|
|
1839
1849
|
this._fn(); // 执行业务
|
|
1850
|
+
|
|
1851
|
+
if (this._loopId !== curLoopId) return;
|
|
1852
|
+
|
|
1840
1853
|
this._timerId = setTimeout(loop, this._ms);
|
|
1841
1854
|
};
|
|
1842
1855
|
loop(); // 立即执行第一次
|
|
@@ -1846,6 +1859,7 @@ registerProcessor('audio-stream-resampler-processor', AudioStreamResamplerProces
|
|
|
1846
1859
|
* 停止定时器。
|
|
1847
1860
|
*/
|
|
1848
1861
|
stop() {
|
|
1862
|
+
this._loopId = null;
|
|
1849
1863
|
if (this._timerId !== null) {
|
|
1850
1864
|
clearTimeout(this._timerId);
|
|
1851
1865
|
this._timerId = null;
|
|
@@ -2098,6 +2112,181 @@ registerProcessor('audio-stream-resampler-processor', AudioStreamResamplerProces
|
|
|
2098
2112
|
}
|
|
2099
2113
|
|
|
2100
2114
|
return path.reverse();
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
/**
|
|
2118
|
+
* 处理函数的返回值类型,用于控制节点是否添加。
|
|
2119
|
+
* @typedef {Object} TransformTreeDataWithExtra_HandlerResult
|
|
2120
|
+
* @property {boolean} [isAdd] - 是否将该节点添加到树中。如果为 false,则过滤掉该节点。
|
|
2121
|
+
*/
|
|
2122
|
+
|
|
2123
|
+
/**
|
|
2124
|
+
* 最终输出的树形结构的字段配置。
|
|
2125
|
+
* @typedef {Object} TransformTreeDataWithExtra_TreeDataOption
|
|
2126
|
+
* @property {string} [idKey="key"] - 最终树节点的唯一标识字段名。
|
|
2127
|
+
* @property {string} [titleKey="title"] - 最终树节点的标题显示字段名。
|
|
2128
|
+
* @property {string} [childrenKey="children"] - 最终树节点的子节点列表字段名。
|
|
2129
|
+
*/
|
|
2130
|
+
|
|
2131
|
+
/**
|
|
2132
|
+
* 主数据(父节点)的相关配置选项。
|
|
2133
|
+
* @typedef {Object} TransformTreeDataWithExtra_NodeOption
|
|
2134
|
+
* @property {string} [idPrefix] - 节点 ID 的前缀。
|
|
2135
|
+
* @property {string} [idKey="id"] - 原始数据中作为唯一标识的字段名。
|
|
2136
|
+
* @property {string} [titleKey="name"] - 原始数据中作为标题的字段名。
|
|
2137
|
+
* @property {string} [childrenKey="children"] - 原始数据中子节点列表的字段名。
|
|
2138
|
+
* @property {Record<string, any>} [assignData] - 需要额外合并到每个树节点上的静态属性。
|
|
2139
|
+
* @property {string} [rawDataKey] - 如果提供,会将原始节点数据对象挂载到树节点的此字段下。
|
|
2140
|
+
* @property {Object<string, any>} [nodeDataId2Obj] - (副作用) 引用传递的对象,用于建立 id -> 原始数据的映射。
|
|
2141
|
+
* @property {function(object, object): TransformTreeDataWithExtra_HandlerResult | void} [nodeDataHandler] - 对每个主节点进行处理的回调函数。
|
|
2142
|
+
*/
|
|
2143
|
+
|
|
2144
|
+
/**
|
|
2145
|
+
* 额外数据(子节点)的相关配置选项。
|
|
2146
|
+
* @typedef {Object} TransformTreeDataWithExtra_ExtraOption
|
|
2147
|
+
* @property {string} [idPrefix] - 额外节点 ID 的前缀。
|
|
2148
|
+
* @property {string} [idKey="id"] - 额外数据中作为唯一标识的字段名。
|
|
2149
|
+
* @property {string} [titleKey="name"] - 额外数据中作为标题的字段名。
|
|
2150
|
+
* @property {string} [childrenKey="extraChildren"] - 在主节点上查找额外数据列表的字段名。
|
|
2151
|
+
* @property {Record<string, any>} [assignData] - 需要额外合并到每个额外树节点上的静态属性。
|
|
2152
|
+
* @property {string} [rawDataKey] - 如果提供,会将原始额外数据对象挂载到树节点的此字段下。
|
|
2153
|
+
* @property {Object<string, any>} [extraDataId2Obj] - (副作用) 引用传递的对象,用于建立 id -> 额外数据的映射。
|
|
2154
|
+
* @property {function(object, object, object): TransformTreeDataWithExtra_HandlerResult | void} [extraDataHandler] - 对每个额外节点进行处理的回调函数。
|
|
2155
|
+
*/
|
|
2156
|
+
|
|
2157
|
+
/**
|
|
2158
|
+
* 将平铺或嵌套的原始数据转换为标准树形结构。
|
|
2159
|
+
* 支持将外部“额外数据”节点作为子节点插入到主节点层级中。
|
|
2160
|
+
* 支持自定义字段映射、ID 前缀、数据挂载以及通过回调函数过滤节点。
|
|
2161
|
+
*
|
|
2162
|
+
* @template T
|
|
2163
|
+
* @param {Array<T>} data - 原始数据数组。
|
|
2164
|
+
* @param {TransformTreeDataWithExtra_ExtraOption} [extraOption] - 额外数据(子节点)的相关配置选项。
|
|
2165
|
+
* @param {TransformTreeDataWithExtra_NodeOption} [nodeOption] - 主数据(父节点)的相关配置选项。
|
|
2166
|
+
* @param {TransformTreeDataWithExtra_TreeDataOption} [treeDataOption] - 最终输出的树形结构的字段配置选项。
|
|
2167
|
+
* @returns {Array<object>} 转换后的树形数据数组。
|
|
2168
|
+
*/
|
|
2169
|
+
function transformTreeDataWithExtra(data, extraOption = {}, nodeOption = {}, treeDataOption = {}) {
|
|
2170
|
+
const { idPrefix: nodeIdPrefix, idKey: nodeIdKey = "id", titleKey: nodeTitleKey = "name", childrenKey: nodeChildrenKey = "children", assignData: nodeAssignData = {}, rawDataKey: nodeRawDataKey, nodeDataId2Obj, nodeDataHandler } = nodeOption;
|
|
2171
|
+
const { idPrefix: extraIdPrefix, idKey: extraIdKey = "id", titleKey: extraTitleKey = "name", childrenKey: extraChildrenKey = "extraChildren", assignData: extraAssignData = {}, rawDataKey: extraRawDataKey, extraDataId2Obj, extraDataHandler } = extraOption;
|
|
2172
|
+
|
|
2173
|
+
const { idKey: treeIdKey = "key", titleKey: treeTitleKey = "title", childrenKey: treeChildrenKey = "children" } = treeDataOption;
|
|
2174
|
+
|
|
2175
|
+
const transformNode = (node) => {
|
|
2176
|
+
const treeNode = {
|
|
2177
|
+
[treeIdKey]: isNonEmptyString(nodeIdPrefix) ? nodeIdPrefix + node[nodeIdKey] : node[nodeIdKey],
|
|
2178
|
+
[treeTitleKey]: node[nodeTitleKey],
|
|
2179
|
+
[treeChildrenKey]: [],
|
|
2180
|
+
...nodeAssignData
|
|
2181
|
+
};
|
|
2182
|
+
if (isNonEmptyString(nodeRawDataKey)) {
|
|
2183
|
+
treeNode[nodeRawDataKey] = node;
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
if (Array.isArray(node[nodeChildrenKey]) && node[nodeChildrenKey].length > 0) {
|
|
2187
|
+
treeNode[treeChildrenKey] = node[nodeChildrenKey].map((child) => transformNode(child)).filter((child) => child !== null);
|
|
2188
|
+
}
|
|
2189
|
+
|
|
2190
|
+
if (Array.isArray(node[extraChildrenKey]) && node[extraChildrenKey].length > 0) {
|
|
2191
|
+
const isValidExtraDataId2Obj = typeof extraDataId2Obj === "object" && extraDataId2Obj !== null;
|
|
2192
|
+
const extraNodes = [];
|
|
2193
|
+
for (const extraItem of node[extraChildrenKey]) {
|
|
2194
|
+
if (isValidExtraDataId2Obj) {
|
|
2195
|
+
extraDataId2Obj[extraItem[extraIdKey]] = extraItem;
|
|
2196
|
+
}
|
|
2197
|
+
const extraNode = {
|
|
2198
|
+
[treeIdKey]: isNonEmptyString(extraIdPrefix) ? extraIdPrefix + extraItem[extraIdKey] : extraItem[extraIdKey],
|
|
2199
|
+
[treeTitleKey]: extraItem[extraTitleKey],
|
|
2200
|
+
[treeChildrenKey]: [],
|
|
2201
|
+
...extraAssignData
|
|
2202
|
+
};
|
|
2203
|
+
if (isNonEmptyString(extraRawDataKey)) {
|
|
2204
|
+
extraNode[extraRawDataKey] = extraItem;
|
|
2205
|
+
}
|
|
2206
|
+
if (typeof extraDataHandler === "function") {
|
|
2207
|
+
const result = extraDataHandler(extraNode, extraItem, node);
|
|
2208
|
+
if (result?.isAdd === false) continue;
|
|
2209
|
+
}
|
|
2210
|
+
extraNodes.push(extraNode);
|
|
2211
|
+
}
|
|
2212
|
+
treeNode[treeChildrenKey] = [...treeNode[treeChildrenKey], ...extraNodes];
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2215
|
+
if (typeof nodeDataId2Obj === "object" && nodeDataId2Obj !== null) {
|
|
2216
|
+
nodeDataId2Obj[node[nodeIdKey]] = node;
|
|
2217
|
+
}
|
|
2218
|
+
|
|
2219
|
+
if (typeof nodeDataHandler === "function") {
|
|
2220
|
+
const result = nodeDataHandler(treeNode, node);
|
|
2221
|
+
if (result?.isAdd === false) {
|
|
2222
|
+
return null;
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
return treeNode;
|
|
2227
|
+
};
|
|
2228
|
+
|
|
2229
|
+
return data.map((item) => transformNode(item)).filter((item) => item !== null);
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
/**
|
|
2233
|
+
* 自定义过滤函数的类型定义。
|
|
2234
|
+
* @callback FilterTreeData_FilterFn
|
|
2235
|
+
* @param {object} node - 当前遍历到的树节点对象。
|
|
2236
|
+
* @param {string | number} filterValue - 当前用于过滤的值。
|
|
2237
|
+
* @param {Array<object>} [children] - 当前节点的子节点数组(原始数据)。
|
|
2238
|
+
* @returns {boolean} 返回 true 表示保留该节点,false 表示过滤掉。
|
|
2239
|
+
*/
|
|
2240
|
+
|
|
2241
|
+
/**
|
|
2242
|
+
* 递归过滤树形数据。
|
|
2243
|
+
*
|
|
2244
|
+
* 该函数会保留符合条件的节点。特别地,**即使当前节点本身不匹配条件,只要其子孙节点中有匹配项,该节点也会被保留**,
|
|
2245
|
+
* 从而保证过滤后的树结构能展示出匹配节点的完整路径。
|
|
2246
|
+
*
|
|
2247
|
+
* @template T
|
|
2248
|
+
* @param {Array<T>} treeData - 源树形数据数组。
|
|
2249
|
+
* @param {string | number} filterValue - 用于过滤的关键字。
|
|
2250
|
+
* @param {string} [filterKey="name"] - 节点对象中用于匹配的字段名。默认为 "name"。如果提供了 filterFn 则此项无效。
|
|
2251
|
+
* @param {string} [childrenKey="children"] - 节点对象中存储子数组的字段名。默认为 "children"。
|
|
2252
|
+
* @param {FilterTreeData_FilterFn} [filterFn] - 自定义过滤函数。如果提供,将忽略 filterKey,使用此函数的返回值判断是否匹配。
|
|
2253
|
+
* @returns {Array<T>} 过滤后的新树形数据数组。注意:返回的是节点对象的浅拷贝。
|
|
2254
|
+
*/
|
|
2255
|
+
function filterTreeData(treeData, filterValue, filterKey = "name", childrenKey = "children", filterFn) {
|
|
2256
|
+
if (!Array.isArray(treeData) || treeData.length === 0) {
|
|
2257
|
+
return [];
|
|
2258
|
+
}
|
|
2259
|
+
|
|
2260
|
+
if (filterValue == null || filterValue === "") {
|
|
2261
|
+
return treeData.map((node) => ({ ...node }));
|
|
2262
|
+
}
|
|
2263
|
+
|
|
2264
|
+
const result = [];
|
|
2265
|
+
|
|
2266
|
+
for (const node of treeData) {
|
|
2267
|
+
const newNode = { ...node };
|
|
2268
|
+
const children = node[childrenKey];
|
|
2269
|
+
|
|
2270
|
+
// 后代节点
|
|
2271
|
+
let isDescendantMatch = false;
|
|
2272
|
+
if (Array.isArray(children)) {
|
|
2273
|
+
const newChildren = filterTreeData(children, filterValue, filterKey, childrenKey, filterFn);
|
|
2274
|
+
newNode[childrenKey] = newChildren;
|
|
2275
|
+
isDescendantMatch = newChildren.length > 0;
|
|
2276
|
+
}
|
|
2277
|
+
|
|
2278
|
+
if (isDescendantMatch) {
|
|
2279
|
+
result.push(newNode);
|
|
2280
|
+
} else {
|
|
2281
|
+
// 当前节点
|
|
2282
|
+
const isMatch = typeof filterFn === "function" ? filterFn(node, filterValue, children) : node[filterKey]?.toString().includes(filterValue);
|
|
2283
|
+
|
|
2284
|
+
if (isMatch) {
|
|
2285
|
+
result.push(newNode);
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
return result;
|
|
2101
2290
|
}
|
|
2102
2291
|
|
|
2103
2292
|
/**
|
|
@@ -2522,6 +2711,7 @@ registerProcessor('audio-stream-resampler-processor', AudioStreamResamplerProces
|
|
|
2522
2711
|
exports.downloadJSON = downloadJSON;
|
|
2523
2712
|
exports.extractFullyCheckedKeys = extractFullyCheckedKeys;
|
|
2524
2713
|
exports.fetchOrDownloadByUrl = fetchOrDownloadByUrl;
|
|
2714
|
+
exports.filterTreeData = filterTreeData;
|
|
2525
2715
|
exports.findObjAttrValueById = findObjAttrValueById;
|
|
2526
2716
|
exports.findTreeNodeById = findTreeNodeById;
|
|
2527
2717
|
exports.findTreeNodePath = findTreeNodePath;
|
|
@@ -2539,7 +2729,7 @@ registerProcessor('audio-stream-resampler-processor', AudioStreamResamplerProces
|
|
|
2539
2729
|
exports.isBlob = isBlob;
|
|
2540
2730
|
exports.isDate = isDate;
|
|
2541
2731
|
exports.isFunction = isFunction;
|
|
2542
|
-
exports.isNonEmptyString = isNonEmptyString;
|
|
2732
|
+
exports.isNonEmptyString = isNonEmptyString$1;
|
|
2543
2733
|
exports.isPlainObject = isPlainObject;
|
|
2544
2734
|
exports.isPromise = isPromise;
|
|
2545
2735
|
exports.millisecond2Duration = millisecond2Duration;
|
|
@@ -2560,6 +2750,7 @@ registerProcessor('audio-stream-resampler-processor', AudioStreamResamplerProces
|
|
|
2560
2750
|
exports.shuffle = shuffle;
|
|
2561
2751
|
exports.throttle = throttle;
|
|
2562
2752
|
exports.toDate = toDate;
|
|
2753
|
+
exports.transformTreeDataWithExtra = transformTreeDataWithExtra;
|
|
2563
2754
|
|
|
2564
2755
|
}));
|
|
2565
2756
|
//# sourceMappingURL=a2bei4.utils.umd.js.map
|