util-helpers 4.15.2 → 4.15.3

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.
@@ -537,7 +537,7 @@
537
537
  }
538
538
 
539
539
  // eslint-disable-next-line no-undef
540
- var version = "4.15.2";
540
+ var version = "4.15.3";
541
541
 
542
542
  /**
543
543
  * 打印警告信息
@@ -2025,20 +2025,24 @@
2025
2025
  * @returns {string} 处理后的字符
2026
2026
  * @example
2027
2027
  *
2028
- * // 手机号
2028
+ * // 手机号 前3后4
2029
2029
  * replaceChar('13000000000'); // 130****0000
2030
2030
  *
2031
- * // 身份证
2032
- * replaceChar('130701199310302288'); // 130***********2288
2031
+ * // 身份证 前6后4
2032
+ * replaceChar('130701199310302288', { start: 6, end: -4 }); // 130701********2288
2033
2033
  *
2034
- * // 邮箱
2034
+ * // 邮箱 @前两位
2035
2035
  * const email = '12345@qq.com'
2036
+ * const emailAtIndex = email.indexOf('@');
2037
+ * replaceChar(email, { start: emailAtIndex - 2, end: emailAtIndex }); // 123**@qq.com
2038
+ * // 邮箱 前2和@后面内容,固定替换字符4位
2036
2039
  * replaceChar(email, {start: 2, end: email.indexOf('@'), repeat: 4}); // 12****@qq.com
2037
2040
  *
2038
- * // 银行卡号
2041
+ * // 银行卡号 只展示后4位,固定替换字符4位
2039
2042
  * replaceChar('6228480402564890018', {start: 0, end: -4, repeat: 4}); // ****0018
2040
- *
2041
- * // 带格式的银行卡号,忽略空字符串
2043
+ * // 银行卡号 前6后4
2044
+ * replaceChar('6228480402564890018', { start: 6, end: -4 }); // 622848*********0018
2045
+ * // 银行卡号 前4后3 忽略格式的空格
2042
2046
  * replaceChar('6228 4804 0256 4890 018', {start: 4, end: -4, exclude: ' '}); // 6228 **** **** **** 018
2043
2047
  *
2044
2048
  * // 用户名
@@ -2698,343 +2702,144 @@
2698
2702
  }
2699
2703
 
2700
2704
  /**
2701
- * 转换字段名,返回一个转换字段后的值,不改变原值。
2702
- *
2705
+ * 精确乘法,支持多个数相乘,乘数默认为 1 。
2706
+ *
2703
2707
  * @static
2704
- * @alias module:Processor.transformFieldNames
2705
- * @since 4.14.0
2706
- * @template {*} D
2707
- * @template {Record<string, keyof D>} F
2708
- * @template {string} C
2709
- * @param {D[]} data 对象数组。如果是树结构数据,需要指定第三个参数 childrenField
2710
- * @param {F} fieldNames 字段名映射
2711
- * @param {C} [childrenField] 子级数据字段名
2712
- * @param {'spread'|'self'} [nodeAssign='spread'] 节点赋值方式。spread表示使用展开运算符创建新值,self表示使用自身对象。
2713
- * @returns {import('./transformFieldNames.type.js').TransformFieldNames<D, F, C>}
2708
+ * @alias module:Math.times
2709
+ * @since 3.1.0
2710
+ * @param {...number|string} nums 相乘的数
2711
+ * @returns {number} 乘积
2714
2712
  * @example
2713
+ *
2714
+ * times(3, 0.6); // 1.8
2715
+ * times(3, 0.6, 2); // 3.6
2716
+ * times(3, 0.6, 2, 10); // 36
2715
2717
  *
2716
- * const options = [{code: '1', name: 'one'},{code:'2', name:'two'}];
2717
- * const newOptions = transformFieldNames(options, {label: 'name', value: 'code'});
2718
- * // [{value: '1', label: 'one'},{value:'2', label:'two'}]
2719
- *
2720
- * // 嵌套数据,指定子级字段名 children
2721
- * const options2 = [{code: '1', name: 'one'},{code:'2', name:'two', children: [{code:'2-1', name:'two-one', children: [{code: '2-1-1', name:'two-one-one'}]}]}];
2722
- * const newOptions2 = transformFieldNames(options2, {label: 'name', value: 'code'}, 'children');
2723
- * // [{value: '1', label: 'one'},{value:'2', label:'two', children: [{value: '2-1', label:'two-one', children: [{value: '2-1-1', label:'two-one-one'}]}]}]
2724
- *
2725
- * const options3 = [{code: '1', name: 'one'},{code:'2', name:'two', childs: [{code:'2-1', name:'two-one'}]}];
2726
- * const newOptions3 = transformFieldNames(options3, {label: 'name', value: 'code'}, 'childs');
2727
- * // [{value: '1', label: 'one'},{value:'2', label:'two', childs: [{value: '2-1', label:'two-one'}]}]
2728
- *
2729
- * // 嵌套数据,并替换子集字段名
2730
- * const newOptions4 = transformFieldNames(options3, {label: 'name', value: 'code', children: 'childs'}, 'childs');
2731
- * // [{value: '1', label: 'one'},{value:'2', label:'two', children: [{value: '2-1', label:'two-one'}]}]
2732
2718
  */
2733
- function transformFieldNames(data, fieldNames, childrenField) {
2734
- var nodeAssign = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'spread';
2735
- if (!Array.isArray(data)) {
2736
- return data;
2719
+ function times() {
2720
+ for (var _len = arguments.length, nums = new Array(_len), _key = 0; _key < _len; _key++) {
2721
+ nums[_key] = arguments[_key];
2737
2722
  }
2738
- if (data.length <= 0) {
2739
- // @ts-ignore
2740
- return [];
2723
+ var num1 = nums[0],
2724
+ _nums$ = nums[1],
2725
+ num2 = _nums$ === void 0 ? 1 : _nums$,
2726
+ rest = nums.slice(2);
2727
+ if (rest.length > 0) {
2728
+ return times.apply(void 0, [times(num1, num2)].concat(_toConsumableArray(rest)));
2741
2729
  }
2730
+ num1 = transformEffectiveNumber(num1);
2731
+ num2 = transformEffectiveNumber(num2);
2742
2732
 
2743
- /**
2744
- * 递归处理字段名
2745
- *
2746
- * @param {Array.<object>} arr 列表数据
2747
- * @returns {*}
2748
- */
2749
- function recusion(arr) {
2750
- return arr.map(function (item) {
2751
- if (!isObject(item)) {
2752
- return item;
2753
- }
2754
- var newItem = nodeAssign === 'spread' ? _objectSpread2({}, item) : item;
2755
- /** @type {Array.<string>} */
2756
- var delKeys = [];
2757
-
2758
- // 树形数据子节点
2759
- // @ts-ignore
2760
- if (childrenField && Array.isArray(newItem[childrenField]) && newItem[childrenField].length > 0) {
2761
- // @ts-ignore
2762
- newItem[childrenField] = recusion(newItem[childrenField].slice());
2763
- }
2764
-
2765
- // 替换字段名
2766
- Object.keys(fieldNames).forEach(function (newKey) {
2767
- var oldKey = fieldNames[newKey];
2768
- if (oldKey in newItem) {
2769
- // @ts-ignore
2770
- newItem[newKey] = newItem[oldKey];
2771
- // @ts-ignore
2772
- delKeys.push(oldKey);
2773
- }
2774
- });
2733
+ // 兼容处理,如果参数包含无效数值时,返回 NaN
2734
+ // @ts-ignore
2735
+ if (isNaN(num1) || isNaN(num2)) {
2736
+ return Number.NaN;
2737
+ }
2738
+ var num1Changed = float2Fixed(num1);
2739
+ var num2Changed = float2Fixed(num2);
2740
+ var baseNum = digitLength(num1) + digitLength(num2);
2741
+ var leftValue = num1Changed * num2Changed;
2742
+ checkBoundary(leftValue);
2743
+ return leftValue / Math.pow(10, baseNum);
2744
+ }
2775
2745
 
2776
- // 删除旧字段
2777
- if (delKeys.length > 0) {
2778
- delKeys.forEach(function (delKey) {
2779
- // @ts-ignore
2780
- delete newItem[delKey];
2781
- });
2782
- }
2783
- return newItem;
2784
- });
2746
+ /**
2747
+ * 精确加法,支持多个数相加,加数默认为 0
2748
+ *
2749
+ * @static
2750
+ * @alias module:Math.plus
2751
+ * @since 3.1.0
2752
+ * @param {...number|string} nums 相加的数
2753
+ * @returns {number} 总和
2754
+ * @example
2755
+ *
2756
+ * plus(0.1, 0.2); // 0.3
2757
+ * plus(0.1, 0.2, 0.3); // 0.6
2758
+ * plus(0.1, 0.2, 0.3, 0.4); // 1
2759
+ *
2760
+ */
2761
+ function plus() {
2762
+ for (var _len = arguments.length, nums = new Array(_len), _key = 0; _key < _len; _key++) {
2763
+ nums[_key] = arguments[_key];
2785
2764
  }
2765
+ var num1 = nums[0],
2766
+ _nums$ = nums[1],
2767
+ num2 = _nums$ === void 0 ? 0 : _nums$,
2768
+ rest = nums.slice(2);
2769
+ if (rest.length > 0) {
2770
+ return plus.apply(void 0, [plus(num1, num2)].concat(_toConsumableArray(rest)));
2771
+ }
2772
+ num1 = transformEffectiveNumber(num1);
2773
+ num2 = transformEffectiveNumber(num2);
2786
2774
 
2775
+ // 兼容处理,如果参数包含无效数值时,返回 NaN
2787
2776
  // @ts-ignore
2788
- return recusion(data.slice());
2777
+ if (isNaN(num1) || isNaN(num2)) {
2778
+ return Number.NaN;
2779
+ }
2780
+ var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
2781
+ return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
2789
2782
  }
2790
2783
 
2791
2784
  /**
2792
- * 递归处理空子级
2785
+ * 精确减法,支持多个数相减,减数默认为 0 。
2786
+ *
2787
+ * @static
2788
+ * @alias module:Math.minus
2789
+ * @since 3.1.0
2790
+ * @param {...number|string} nums 相减的数
2791
+ * @returns {number} 差
2792
+ * @example
2793
+ *
2794
+ * minus(1, 0.9); // 0.1
2795
+ * minus(1, 0.9, 0.02); // 0.08
2796
+ * minus(1, 0.9, 0.02, 0.08); // 0
2793
2797
  *
2794
- * @private
2795
- * @template {Record<string,any>} [T=Record<string,any>]
2796
- * @param {T[]} arr 列表数据
2797
- * @param {object} [options] 配置项
2798
- * @param {string} [options.childrenField='children'] 子级字段名称
2799
- * @param {'none'|'null'} [options.emptyChildrenValue='none'] 子级为空时的值,none表示删除该子级,null表示为null,array表示为[]。
2800
2798
  */
2801
- function processEmptyChildren(arr, options) {
2802
- var _ref = options || {},
2803
- _ref$childrenField = _ref.childrenField,
2804
- childrenField = _ref$childrenField === void 0 ? 'children' : _ref$childrenField,
2805
- _ref$emptyChildrenVal = _ref.emptyChildrenValue,
2806
- emptyChildrenValue = _ref$emptyChildrenVal === void 0 ? 'none' : _ref$emptyChildrenVal;
2807
- arr.forEach(function (item) {
2808
- // if (isObject(item) && Array.isArray(item[childrenField])) {
2809
- if (item[childrenField].length <= 0) {
2810
- if (emptyChildrenValue === 'null') {
2811
- // @ts-ignore
2812
- item[childrenField] = null;
2813
- // } else if (emptyChildrenValue === 'none') { // emptyChildrenValue='array' 不会执行该内部方法
2814
- } else {
2815
- delete item[childrenField];
2816
- }
2817
- } else {
2818
- processEmptyChildren(item[childrenField], options);
2819
- }
2820
- // }
2821
- });
2799
+ function minus() {
2800
+ for (var _len = arguments.length, nums = new Array(_len), _key = 0; _key < _len; _key++) {
2801
+ nums[_key] = arguments[_key];
2802
+ }
2803
+ var num1 = nums[0],
2804
+ _nums$ = nums[1],
2805
+ num2 = _nums$ === void 0 ? 0 : _nums$,
2806
+ rest = nums.slice(2);
2807
+ if (rest.length > 0) {
2808
+ return minus.apply(void 0, [minus(num1, num2)].concat(_toConsumableArray(rest)));
2809
+ }
2810
+ num1 = transformEffectiveNumber(num1);
2811
+ num2 = transformEffectiveNumber(num2);
2812
+
2813
+ // 兼容处理,如果参数包含无效数值时,返回 NaN
2814
+ // @ts-ignore
2815
+ if (isNaN(num1) || isNaN(num2)) {
2816
+ return Number.NaN;
2817
+ }
2818
+ var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
2819
+ return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
2822
2820
  }
2823
2821
 
2824
2822
  /**
2825
- * 列表数据转树结构
2826
- *
2823
+ * 精确除法,支持多个数相除,除数默认为 1 。
2824
+ *
2827
2825
  * @static
2828
- * @alias module:Processor.listToTree
2829
- * @since 4.14.0
2830
- * @template {Record<string,any>} [T=Record<string,any>]
2831
- * @template {*} [R=T&Record<string,any>]
2832
- * @param {T[]} list 列表数据
2833
- * @param {object} [options] 配置项
2834
- * @param {string} [options.keyField='id'] 当前数据的键值字段名称
2835
- * @param {string} [options.parentField='pid'] 当前数据的父级字段名称
2836
- * @param {string} [options.childrenField='children'] 子级字段名称
2837
- * @param {'none'|'null'|'array'} [options.emptyChildrenValue='none'] 子级为空时的值,none表示删除该子级,null表示为null,array表示为[]。
2838
- * @param {'spread'|'self'} [options.nodeAssign='spread'] 节点赋值方式。spread表示使用展开运算符创建新值,self表示使用自身对象。
2839
- * @returns {R[]} 树结构
2826
+ * @alias module:Math.divide
2827
+ * @since 3.1.0
2828
+ * @param {...number|string} nums 被除数和除数
2829
+ * @returns {number} 商数
2840
2830
  * @example
2831
+ *
2832
+ * divide(1.21); // 1.21 除数默认为 1 ,即 1.21/1 = 1.21
2833
+ * divide(1.21, 1.1); // 1.1
2834
+ * divide(1000, 10, 10); // 10
2835
+ * divide(1000, 10, 10, 10); // 1
2841
2836
  *
2842
- * const menus = [
2843
- * { id: '1', name: '首页', code: 'trade', pid: null },
2844
- * { id: '2', name: '交易管理', code: 'trade', pid: null },
2845
- * { id: '3', name: '交易查询', code: 'trade-1', pid: '2' },
2846
- * { id: '4', name: '交易查询-查询操作', code: 'trade-1-1', pid: '3' },
2847
- * { id: '5', name: '权限管理', code: 'authorization', pid: null },
2848
- * { id: '6', name: '角色管理', code: 'authorization-1', pid: '5' },
2849
- * { id: '7', name: '用户管理', code: 'authorization-2', pid: '5' }
2850
- * ];
2851
- * listToTree(menus);
2852
- * // [{"id":"1","name":"首页","code":"trade","pid":null},{"id":"2","name":"交易管理","code":"trade","pid":null,"children":[{"id":"3","name":"交易查询","code":"trade-1","pid":"2","children":[{"id":"4","name":"交易查询-查询操作","code":"trade-1-1","pid":"3"}]}]},{"id":"5","name":"权限管理","code":"authorization","pid":null,"children":[{"id":"6","name":"角色管理","code":"authorization-1","pid":"5"},{"id":"7","name":"用户管理","code":"authorization-2","pid":"5"}]}]
2853
- *
2854
- * // 自定义子级字段名
2855
- * listToTree(basicMenus, { childrenField: 'childs' });
2856
- * // [{"id":"1","name":"首页","code":"trade","pid":null},{"id":"2","name":"交易管理","code":"trade","pid":null,"childs":[{"id":"3","name":"交易查询","code":"trade-1","pid":"2","childs":[{"id":"4","name":"交易查询-查询操作","code":"trade-1-1","pid":"3"}]}]},{"id":"5","name":"权限管理","code":"authorization","pid":null,"childs":[{"id":"6","name":"角色管理","code":"authorization-1","pid":"5"},{"id":"7","name":"用户管理","code":"authorization-2","pid":"5"}]}]
2837
+ * divide(); // NaN 如果没有传入参数,被除数默认为 undefined 。 Number(undefined) 转换为 NaN ,NaN/1 = NaN
2838
+ * divide(null); // 0 Number(null) 转换为 0 0/1 = 0
2839
+ * divide('1.5 ', 0.5); // 3 Number('1.5 ') 转换为 1.5 ,1.5/0.5 = 3
2857
2840
  *
2858
2841
  */
2859
- function listToTree(list, options) {
2860
- var _ref2 = options || {},
2861
- _ref2$keyField = _ref2.keyField,
2862
- keyField = _ref2$keyField === void 0 ? 'id' : _ref2$keyField,
2863
- _ref2$parentField = _ref2.parentField,
2864
- parentField = _ref2$parentField === void 0 ? 'pid' : _ref2$parentField,
2865
- _ref2$childrenField = _ref2.childrenField,
2866
- childrenField = _ref2$childrenField === void 0 ? 'children' : _ref2$childrenField,
2867
- _ref2$emptyChildrenVa = _ref2.emptyChildrenValue,
2868
- emptyChildrenValue = _ref2$emptyChildrenVa === void 0 ? 'none' : _ref2$emptyChildrenVa,
2869
- _ref2$nodeAssign = _ref2.nodeAssign,
2870
- nodeAssign = _ref2$nodeAssign === void 0 ? 'spread' : _ref2$nodeAssign;
2871
-
2872
- /** @type {R[]} */
2873
- var tree = [];
2874
-
2875
- /** @type {Object.<string, T[]>} */
2876
- var record = {};
2877
- if (!Array.isArray(list)) {
2878
- return tree;
2879
- }
2880
- list.forEach(function (item) {
2881
- if (isObject(item)) {
2882
- var newItem = nodeAssign === 'spread' ? _objectSpread2({}, item) : item;
2883
-
2884
- /** @type {string} */
2885
- var id = newItem[keyField];
2886
-
2887
- /** @type {string} */
2888
- var pid = newItem[parentField];
2889
- if (record[id]) {
2890
- // @ts-ignore
2891
- newItem[childrenField] = record[id];
2892
- } else {
2893
- // @ts-ignore
2894
- newItem[childrenField] = record[id] = [];
2895
- }
2896
- if (pid) {
2897
- if (!record[pid]) {
2898
- record[pid] = [newItem];
2899
- } else {
2900
- record[pid].push(newItem);
2901
- }
2902
- } else {
2903
- // @ts-ignore
2904
- tree.push(newItem);
2905
- }
2906
- }
2907
- });
2908
- if (emptyChildrenValue !== 'array') {
2909
- // @ts-ignore
2910
- processEmptyChildren(tree, options);
2911
- }
2912
- return tree;
2913
- }
2914
-
2915
- /**
2916
- * 树结构转列表数据
2917
- *
2918
- * @static
2919
- * @alias module:Processor.treeToList
2920
- * @since 4.14.0
2921
- * @template {Record<string,any>} T
2922
- * @template {keyof T} K
2923
- * @template {Omit<T, K>} R
2924
- * @param {T[]} tree 列表数据
2925
- * @param {K} childrenField 子级字段名称
2926
- * @returns {R[]} 列表数据
2927
- * @example
2928
- * const menus = [{ "id": "1", "name": "首页", "code": "trade", "pid": null }, { "id": "2", "name": "交易管理", "code": "trade", "pid": null, "children": [{ "id": "3", "name": "交易查询", "code": "trade-1", "pid": "2", "children": [{ "id": "4", "name": "交易查询-查询操作", "code": "trade-1-1", "pid": "3" }] }] }, { "id": "5", "name": "权限管理", "code": "authorization", "pid": null, "children": [{ "id": "6", "name": "角色管理", "code": "authorization-1", "pid": "5" }, { "id": "7", "name": "用户管理", "code": "authorization-2", "pid": "5" }] }];
2929
- *
2930
- * treeToList(menus, 'children'));
2931
- * // [{"id":"1","name":"首页","code":"trade","pid":null},{"id":"2","name":"交易管理","code":"trade","pid":null},{"id":"3","name":"交易查询","code":"trade-1","pid":"2"},{"id":"4","name":"交易查询-查询操作","code":"trade-1-1","pid":"3"},{"id":"5","name":"权限管理","code":"authorization","pid":null},{"id":"6","name":"角色管理","code":"authorization-1","pid":"5"},{"id":"7","name":"用户管理","code":"authorization-2","pid":"5"}]
2932
- */
2933
- function treeToList(tree, childrenField) {
2934
- /** @type {R[]} */
2935
- var list = [];
2936
- if (!Array.isArray(tree)) {
2937
- return list;
2938
- }
2939
-
2940
- /**
2941
- * 递归遍历
2942
- * @param {T[]} arr 列表数据
2943
- */
2944
- function recusion(arr) {
2945
- arr.forEach(function (item) {
2946
- if (isObject(item)) {
2947
- var newItem = _objectSpread2({}, item);
2948
- // @ts-ignore
2949
- list.push(newItem);
2950
- if (newItem[childrenField]) {
2951
- if (Array.isArray(newItem[childrenField]) && newItem[childrenField].length > 0) {
2952
- recusion(newItem[childrenField]);
2953
- }
2954
- delete newItem[childrenField];
2955
- }
2956
- } else {
2957
- // @ts-ignore
2958
- list.push(item);
2959
- }
2960
- });
2961
- }
2962
- recusion(tree);
2963
- return list;
2964
- }
2965
-
2966
- /**
2967
- * 过滤/筛选树节点。<br/><br/>如果某节点被过滤掉,它的子节点也一并抛弃
2968
- *
2969
- * @static
2970
- * @alias module:Processor.filterTree
2971
- * @since 4.15.0
2972
- * @template {any} T
2973
- * @template {(item: T) => boolean} F
2974
- * @param {T[]} tree 树结构数据
2975
- * @param {F} predicate 遍历每一项执行的函数,参数是当前遍历到的节点数据,如果返回 Truthy ,结果将包含该节点
2976
- * @param {string} [childrenField='children'] 子级字段名
2977
- * @param {'spread'|'self'} [nodeAssign='spread'] 节点赋值方式。spread表示使用展开运算符创建新值,self表示使用自身对象。
2978
- * @returns {T[]}
2979
- * @example
2980
- * const menus = [{ "id": "1", "name": "首页", "code": "trade", "pid": null }, { "id": "2", "name": "交易管理", "code": "trade", "pid": null, "children": [{ "id": "3", "name": "交易查询", "code": "trade-1", "pid": "2", "children": [{ "id": "4", "name": "交易查询-查询操作", "code": "trade-1-1", "pid": "3" }] }] }, { "id": "5", "name": "权限管理", "code": "authorization", "pid": null, "children": [{ "id": "6", "name": "角色管理", "code": "authorization-1", "pid": "5" }, { "id": "7", "name": "用户管理", "code": "authorization-2", "pid": "5" }] }];
2981
- *
2982
- * filterTree(menus, item=>item.name.indexOf('管理') > -1);
2983
- * // [{"id":"2","name":"交易管理","code":"trade","pid":null,"children":[]},{"id":"5","name":"权限管理","code":"authorization","pid":null,"children":[{"id":"6","name":"角色管理","code":"authorization-1","pid":"5"},{"id":"7","name":"用户管理","code":"authorization-2","pid":"5"}]}]
2984
- *
2985
- * // 如果某节点被过滤掉,它的子节点也一并抛弃
2986
- * filterTree(menus, item=>item.id === '7');
2987
- * // []
2988
- *
2989
- * filterTree(menus, item=>item.id === 'not found');
2990
- * // []
2991
- */
2992
- function filterTree(tree, predicate) {
2993
- var childrenField = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'children';
2994
- var nodeAssign = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'spread';
2995
- /** @type {T[]} */
2996
- var result = [];
2997
- if (!Array.isArray(tree)) {
2998
- return result;
2999
- }
3000
- tree.forEach(function (item) {
3001
- var newItem = item;
3002
- if (isObject(item)) {
3003
- // @ts-ignore
3004
- newItem = nodeAssign === 'spread' ? _objectSpread2({}, item) : item;
3005
- }
3006
- if (predicate(newItem)) {
3007
- if (isObject(newItem)) {
3008
- /** @type {T[]|undefined} */
3009
- // @ts-ignore
3010
- var childs = newItem[childrenField];
3011
- if (Array.isArray(childs) && childs.length > 0) {
3012
- // @ts-ignore
3013
- newItem[childrenField] = filterTree(childs, predicate, childrenField, nodeAssign);
3014
- }
3015
- }
3016
- result.push(newItem);
3017
- }
3018
- });
3019
- return result;
3020
- }
3021
-
3022
- /**
3023
- * 精确乘法,支持多个数相乘,乘数默认为 1 。
3024
- *
3025
- * @static
3026
- * @alias module:Math.times
3027
- * @since 3.1.0
3028
- * @param {...number|string} nums 相乘的数
3029
- * @returns {number} 乘积
3030
- * @example
3031
- *
3032
- * times(3, 0.6); // 1.8
3033
- * times(3, 0.6, 2); // 3.6
3034
- * times(3, 0.6, 2, 10); // 36
3035
- *
3036
- */
3037
- function times() {
2842
+ function divide() {
3038
2843
  for (var _len = arguments.length, nums = new Array(_len), _key = 0; _key < _len; _key++) {
3039
2844
  nums[_key] = arguments[_key];
3040
2845
  }
@@ -3043,7 +2848,7 @@
3043
2848
  num2 = _nums$ === void 0 ? 1 : _nums$,
3044
2849
  rest = nums.slice(2);
3045
2850
  if (rest.length > 0) {
3046
- return times.apply(void 0, [times(num1, num2)].concat(_toConsumableArray(rest)));
2851
+ return divide.apply(void 0, [divide(num1, num2)].concat(_toConsumableArray(rest)));
3047
2852
  }
3048
2853
  num1 = transformEffectiveNumber(num1);
3049
2854
  num2 = transformEffectiveNumber(num2);
@@ -3055,190 +2860,67 @@
3055
2860
  }
3056
2861
  var num1Changed = float2Fixed(num1);
3057
2862
  var num2Changed = float2Fixed(num2);
3058
- var baseNum = digitLength(num1) + digitLength(num2);
3059
- var leftValue = num1Changed * num2Changed;
3060
- checkBoundary(leftValue);
3061
- return leftValue / Math.pow(10, baseNum);
2863
+ checkBoundary(num1Changed);
2864
+ checkBoundary(num2Changed);
2865
+ // fix: 类似 10 ** -4 为 0.00009999999999999999,strip 修正
2866
+ return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1))));
3062
2867
  }
3063
2868
 
3064
2869
  /**
3065
- * 精确加法,支持多个数相加,加数默认为 0 。
2870
+ * 四舍五入,支持设置精度
3066
2871
  *
3067
2872
  * @static
3068
- * @alias module:Math.plus
2873
+ * @alias module:Math.round
3069
2874
  * @since 3.1.0
3070
- * @param {...number|string} nums 相加的数
3071
- * @returns {number} 总和
2875
+ * @param {number|string} num 要四舍五入的数字
2876
+ * @param {number} [precision=0] 四舍五入的精度
2877
+ * @returns {number} 四舍五入的数字
3072
2878
  * @example
3073
2879
  *
3074
- * plus(0.1, 0.2); // 0.3
3075
- * plus(0.1, 0.2, 0.3); // 0.6
3076
- * plus(0.1, 0.2, 0.3, 0.4); // 1
2880
+ * round(4.006); // 4
2881
+ * round(4.006, 2); // 4.01
2882
+ * round(4060, -2); // 4100
3077
2883
  *
3078
2884
  */
3079
- function plus() {
3080
- for (var _len = arguments.length, nums = new Array(_len), _key = 0; _key < _len; _key++) {
3081
- nums[_key] = arguments[_key];
3082
- }
3083
- var num1 = nums[0],
3084
- _nums$ = nums[1],
3085
- num2 = _nums$ === void 0 ? 0 : _nums$,
3086
- rest = nums.slice(2);
3087
- if (rest.length > 0) {
3088
- return plus.apply(void 0, [plus(num1, num2)].concat(_toConsumableArray(rest)));
3089
- }
3090
- num1 = transformEffectiveNumber(num1);
3091
- num2 = transformEffectiveNumber(num2);
2885
+ function round(num) {
2886
+ var precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
2887
+ num = transformEffectiveNumber(num);
3092
2888
 
3093
2889
  // 兼容处理,如果参数包含无效数值时,返回 NaN
3094
2890
  // @ts-ignore
3095
- if (isNaN(num1) || isNaN(num2)) {
2891
+ if (isNaN(num)) {
3096
2892
  return Number.NaN;
3097
2893
  }
3098
- var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
3099
- return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
2894
+ var base = Math.pow(10, precision);
2895
+ return divide(Math.round(times(num, base)), base);
3100
2896
  }
3101
2897
 
3102
2898
  /**
3103
- * 精确减法,支持多个数相减,减数默认为 0
2899
+ * 等待时间返回 Promise 。常用于异步方法中延时。
3104
2900
  *
3105
2901
  * @static
3106
- * @alias module:Math.minus
3107
- * @since 3.1.0
3108
- * @param {...number|string} nums 相减的数
3109
- * @returns {number}
2902
+ * @alias module:Other.waitTime
2903
+ * @since 4.2.0
2904
+ * @param {number} [time=1000] 延时时间,单位毫秒
2905
+ * @returns {Promise<void>}
3110
2906
  * @example
2907
+ *
2908
+ * const test = async ()=>{
2909
+ * await waitTime();
2910
+ * // do something
2911
+ * }
3111
2912
  *
3112
- * minus(1, 0.9); // 0.1
3113
- * minus(1, 0.9, 0.02); // 0.08
3114
- * minus(1, 0.9, 0.02, 0.08); // 0
2913
+ * waitTime(500).then(()=>{
2914
+ * // do something
2915
+ * });
3115
2916
  *
3116
2917
  */
3117
- function minus() {
3118
- for (var _len = arguments.length, nums = new Array(_len), _key = 0; _key < _len; _key++) {
3119
- nums[_key] = arguments[_key];
3120
- }
3121
- var num1 = nums[0],
3122
- _nums$ = nums[1],
3123
- num2 = _nums$ === void 0 ? 0 : _nums$,
3124
- rest = nums.slice(2);
3125
- if (rest.length > 0) {
3126
- return minus.apply(void 0, [minus(num1, num2)].concat(_toConsumableArray(rest)));
3127
- }
3128
- num1 = transformEffectiveNumber(num1);
3129
- num2 = transformEffectiveNumber(num2);
3130
-
3131
- // 兼容处理,如果参数包含无效数值时,返回 NaN
3132
- // @ts-ignore
3133
- if (isNaN(num1) || isNaN(num2)) {
3134
- return Number.NaN;
3135
- }
3136
- var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
3137
- return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
3138
- }
3139
-
3140
- /**
3141
- * 精确除法,支持多个数相除,除数默认为 1 。
3142
- *
3143
- * @static
3144
- * @alias module:Math.divide
3145
- * @since 3.1.0
3146
- * @param {...number|string} nums 被除数和除数
3147
- * @returns {number} 商数
3148
- * @example
3149
- *
3150
- * divide(1.21); // 1.21 除数默认为 1 ,即 1.21/1 = 1.21
3151
- * divide(1.21, 1.1); // 1.1
3152
- * divide(1000, 10, 10); // 10
3153
- * divide(1000, 10, 10, 10); // 1
3154
- *
3155
- * divide(); // NaN 如果没有传入参数,被除数默认为 undefined 。 Number(undefined) 转换为 NaN ,NaN/1 = NaN
3156
- * divide(null); // 0 Number(null) 转换为 0 , 0/1 = 0
3157
- * divide('1.5 ', 0.5); // 3 Number('1.5 ') 转换为 1.5 ,1.5/0.5 = 3
3158
- *
3159
- */
3160
- function divide() {
3161
- for (var _len = arguments.length, nums = new Array(_len), _key = 0; _key < _len; _key++) {
3162
- nums[_key] = arguments[_key];
3163
- }
3164
- var num1 = nums[0],
3165
- _nums$ = nums[1],
3166
- num2 = _nums$ === void 0 ? 1 : _nums$,
3167
- rest = nums.slice(2);
3168
- if (rest.length > 0) {
3169
- return divide.apply(void 0, [divide(num1, num2)].concat(_toConsumableArray(rest)));
3170
- }
3171
- num1 = transformEffectiveNumber(num1);
3172
- num2 = transformEffectiveNumber(num2);
3173
-
3174
- // 兼容处理,如果参数包含无效数值时,返回 NaN
3175
- // @ts-ignore
3176
- if (isNaN(num1) || isNaN(num2)) {
3177
- return Number.NaN;
3178
- }
3179
- var num1Changed = float2Fixed(num1);
3180
- var num2Changed = float2Fixed(num2);
3181
- checkBoundary(num1Changed);
3182
- checkBoundary(num2Changed);
3183
- // fix: 类似 10 ** -4 为 0.00009999999999999999,strip 修正
3184
- return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1))));
3185
- }
3186
-
3187
- /**
3188
- * 四舍五入,支持设置精度
3189
- *
3190
- * @static
3191
- * @alias module:Math.round
3192
- * @since 3.1.0
3193
- * @param {number|string} num 要四舍五入的数字
3194
- * @param {number} [precision=0] 四舍五入的精度
3195
- * @returns {number} 四舍五入的数字
3196
- * @example
3197
- *
3198
- * round(4.006); // 4
3199
- * round(4.006, 2); // 4.01
3200
- * round(4060, -2); // 4100
3201
- *
3202
- */
3203
- function round(num) {
3204
- var precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
3205
- num = transformEffectiveNumber(num);
3206
-
3207
- // 兼容处理,如果参数包含无效数值时,返回 NaN
3208
- // @ts-ignore
3209
- if (isNaN(num)) {
3210
- return Number.NaN;
3211
- }
3212
- var base = Math.pow(10, precision);
3213
- return divide(Math.round(times(num, base)), base);
3214
- }
3215
-
3216
- /**
3217
- * 等待时间返回 Promise 。常用于异步方法中延时。
3218
- *
3219
- * @static
3220
- * @alias module:Other.waitTime
3221
- * @since 4.2.0
3222
- * @param {number} [time=1000] 延时时间,单位毫秒
3223
- * @returns {Promise<void>}
3224
- * @example
3225
- *
3226
- * const test = async ()=>{
3227
- * await waitTime();
3228
- * // do something
3229
- * }
3230
- *
3231
- * waitTime(500).then(()=>{
3232
- * // do something
3233
- * });
3234
- *
3235
- */
3236
- function waitTime() {
3237
- var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1000;
3238
- return new Promise(function (resolve) {
3239
- setTimeout(resolve, time);
3240
- });
3241
- }
2918
+ function waitTime() {
2919
+ var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1000;
2920
+ return new Promise(function (resolve) {
2921
+ setTimeout(resolve, time);
2922
+ });
2923
+ }
3242
2924
 
3243
2925
  // ref: https://github.com/ant-design/ant-design-mobile/blob/v2/components/input-item/index.tsx#L240
3244
2926
 
@@ -3371,11 +3053,333 @@
3371
3053
  return len;
3372
3054
  }
3373
3055
 
3056
+ /**
3057
+ * 转换字段名,返回一个转换字段后的值,不改变原值。
3058
+ *
3059
+ * @static
3060
+ * @alias module:Processor.transformFieldNames
3061
+ * @since 4.14.0
3062
+ * @template {*} D
3063
+ * @template {Record<string, keyof D>} F
3064
+ * @template {string} C
3065
+ * @param {D[]} data 对象数组。如果是树结构数据,需要指定第三个参数 childrenField
3066
+ * @param {F} fieldNames 字段名映射
3067
+ * @param {C} [childrenField] 子级数据字段名
3068
+ * @param {'spread'|'self'} [nodeAssign='spread'] 节点赋值方式。spread表示使用展开运算符创建新值,self表示使用自身对象。
3069
+ * @returns {import('./transformFieldNames.type.js').TransformFieldNames<D, F, C>}
3070
+ * @example
3071
+ *
3072
+ * const options = [{code: '1', name: 'one'},{code:'2', name:'two'}];
3073
+ * const newOptions = transformFieldNames(options, {label: 'name', value: 'code'});
3074
+ * // [{value: '1', label: 'one'},{value:'2', label:'two'}]
3075
+ *
3076
+ * // 嵌套数据,指定子级字段名 children
3077
+ * const options2 = [{code: '1', name: 'one'},{code:'2', name:'two', children: [{code:'2-1', name:'two-one', children: [{code: '2-1-1', name:'two-one-one'}]}]}];
3078
+ * const newOptions2 = transformFieldNames(options2, {label: 'name', value: 'code'}, 'children');
3079
+ * // [{value: '1', label: 'one'},{value:'2', label:'two', children: [{value: '2-1', label:'two-one', children: [{value: '2-1-1', label:'two-one-one'}]}]}]
3080
+ *
3081
+ * const options3 = [{code: '1', name: 'one'},{code:'2', name:'two', childs: [{code:'2-1', name:'two-one'}]}];
3082
+ * const newOptions3 = transformFieldNames(options3, {label: 'name', value: 'code'}, 'childs');
3083
+ * // [{value: '1', label: 'one'},{value:'2', label:'two', childs: [{value: '2-1', label:'two-one'}]}]
3084
+ *
3085
+ * // 嵌套数据,并替换子集字段名
3086
+ * const newOptions4 = transformFieldNames(options3, {label: 'name', value: 'code', children: 'childs'}, 'childs');
3087
+ * // [{value: '1', label: 'one'},{value:'2', label:'two', children: [{value: '2-1', label:'two-one'}]}]
3088
+ */
3089
+ function transformFieldNames(data, fieldNames, childrenField) {
3090
+ var nodeAssign = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'spread';
3091
+ if (!Array.isArray(data)) {
3092
+ return data;
3093
+ }
3094
+ if (data.length <= 0) {
3095
+ // @ts-ignore
3096
+ return [];
3097
+ }
3098
+
3099
+ /**
3100
+ * 递归处理字段名
3101
+ *
3102
+ * @param {Array.<object>} arr 列表数据
3103
+ * @returns {*}
3104
+ */
3105
+ function recusion(arr) {
3106
+ return arr.map(function (item) {
3107
+ if (!isObject(item)) {
3108
+ return item;
3109
+ }
3110
+ var newItem = nodeAssign === 'spread' ? _objectSpread2({}, item) : item;
3111
+ /** @type {Array.<string>} */
3112
+ var delKeys = [];
3113
+
3114
+ // 树形数据子节点
3115
+ // @ts-ignore
3116
+ if (childrenField && Array.isArray(newItem[childrenField]) && newItem[childrenField].length > 0) {
3117
+ // @ts-ignore
3118
+ newItem[childrenField] = recusion(newItem[childrenField].slice());
3119
+ }
3120
+
3121
+ // 替换字段名
3122
+ Object.keys(fieldNames).forEach(function (newKey) {
3123
+ var oldKey = fieldNames[newKey];
3124
+ if (oldKey in newItem) {
3125
+ // @ts-ignore
3126
+ newItem[newKey] = newItem[oldKey];
3127
+ // @ts-ignore
3128
+ delKeys.push(oldKey);
3129
+ }
3130
+ });
3131
+
3132
+ // 删除旧字段
3133
+ if (delKeys.length > 0) {
3134
+ delKeys.forEach(function (delKey) {
3135
+ // @ts-ignore
3136
+ delete newItem[delKey];
3137
+ });
3138
+ }
3139
+ return newItem;
3140
+ });
3141
+ }
3142
+
3143
+ // @ts-ignore
3144
+ return recusion(data.slice());
3145
+ }
3146
+
3147
+ /**
3148
+ * 递归处理空子级
3149
+ *
3150
+ * @private
3151
+ * @template {Record<string,any>} [T=Record<string,any>]
3152
+ * @param {T[]} arr 列表数据
3153
+ * @param {object} [options] 配置项
3154
+ * @param {string} [options.childrenField='children'] 子级字段名称
3155
+ * @param {'none'|'null'} [options.emptyChildrenValue='none'] 子级为空时的值,none表示删除该子级,null表示为null,array表示为[]。
3156
+ */
3157
+ function processEmptyChildren(arr, options) {
3158
+ var _ref = options || {},
3159
+ _ref$childrenField = _ref.childrenField,
3160
+ childrenField = _ref$childrenField === void 0 ? 'children' : _ref$childrenField,
3161
+ _ref$emptyChildrenVal = _ref.emptyChildrenValue,
3162
+ emptyChildrenValue = _ref$emptyChildrenVal === void 0 ? 'none' : _ref$emptyChildrenVal;
3163
+ arr.forEach(function (item) {
3164
+ // if (isObject(item) && Array.isArray(item[childrenField])) {
3165
+ if (item[childrenField].length <= 0) {
3166
+ if (emptyChildrenValue === 'null') {
3167
+ // @ts-ignore
3168
+ item[childrenField] = null;
3169
+ // } else if (emptyChildrenValue === 'none') { // emptyChildrenValue='array' 不会执行该内部方法
3170
+ } else {
3171
+ delete item[childrenField];
3172
+ }
3173
+ } else {
3174
+ processEmptyChildren(item[childrenField], options);
3175
+ }
3176
+ // }
3177
+ });
3178
+ }
3179
+
3180
+ /**
3181
+ * 列表数据转树结构
3182
+ *
3183
+ * @static
3184
+ * @alias module:Tree.listToTree
3185
+ * @since 4.14.0
3186
+ * @template {Record<string,any>} [T=Record<string,any>]
3187
+ * @template {*} [R=T&Record<string,any>]
3188
+ * @param {T[]} list 列表数据
3189
+ * @param {object} [options] 配置项
3190
+ * @param {string} [options.keyField='id'] 当前数据的键值字段名称
3191
+ * @param {string} [options.parentField='pid'] 当前数据的父级字段名称
3192
+ * @param {string} [options.childrenField='children'] 子级字段名称
3193
+ * @param {'none'|'null'|'array'} [options.emptyChildrenValue='none'] 子级为空时的值,none表示删除该子级,null表示为null,array表示为[]。
3194
+ * @param {'spread'|'self'} [options.nodeAssign='spread'] 节点赋值方式。spread表示使用展开运算符创建新值,self表示使用自身对象。
3195
+ * @returns {R[]} 树结构
3196
+ * @example
3197
+ *
3198
+ * const menus = [
3199
+ * { id: '1', name: '首页', code: 'trade', pid: null },
3200
+ * { id: '2', name: '交易管理', code: 'trade', pid: null },
3201
+ * { id: '3', name: '交易查询', code: 'trade-1', pid: '2' },
3202
+ * { id: '4', name: '交易查询-查询操作', code: 'trade-1-1', pid: '3' },
3203
+ * { id: '5', name: '权限管理', code: 'authorization', pid: null },
3204
+ * { id: '6', name: '角色管理', code: 'authorization-1', pid: '5' },
3205
+ * { id: '7', name: '用户管理', code: 'authorization-2', pid: '5' }
3206
+ * ];
3207
+ * listToTree(menus);
3208
+ * // [{"id":"1","name":"首页","code":"trade","pid":null},{"id":"2","name":"交易管理","code":"trade","pid":null,"children":[{"id":"3","name":"交易查询","code":"trade-1","pid":"2","children":[{"id":"4","name":"交易查询-查询操作","code":"trade-1-1","pid":"3"}]}]},{"id":"5","name":"权限管理","code":"authorization","pid":null,"children":[{"id":"6","name":"角色管理","code":"authorization-1","pid":"5"},{"id":"7","name":"用户管理","code":"authorization-2","pid":"5"}]}]
3209
+ *
3210
+ * // 自定义子级字段名
3211
+ * listToTree(basicMenus, { childrenField: 'childs' });
3212
+ * // [{"id":"1","name":"首页","code":"trade","pid":null},{"id":"2","name":"交易管理","code":"trade","pid":null,"childs":[{"id":"3","name":"交易查询","code":"trade-1","pid":"2","childs":[{"id":"4","name":"交易查询-查询操作","code":"trade-1-1","pid":"3"}]}]},{"id":"5","name":"权限管理","code":"authorization","pid":null,"childs":[{"id":"6","name":"角色管理","code":"authorization-1","pid":"5"},{"id":"7","name":"用户管理","code":"authorization-2","pid":"5"}]}]
3213
+ *
3214
+ */
3215
+ function listToTree(list, options) {
3216
+ var _ref2 = options || {},
3217
+ _ref2$keyField = _ref2.keyField,
3218
+ keyField = _ref2$keyField === void 0 ? 'id' : _ref2$keyField,
3219
+ _ref2$parentField = _ref2.parentField,
3220
+ parentField = _ref2$parentField === void 0 ? 'pid' : _ref2$parentField,
3221
+ _ref2$childrenField = _ref2.childrenField,
3222
+ childrenField = _ref2$childrenField === void 0 ? 'children' : _ref2$childrenField,
3223
+ _ref2$emptyChildrenVa = _ref2.emptyChildrenValue,
3224
+ emptyChildrenValue = _ref2$emptyChildrenVa === void 0 ? 'none' : _ref2$emptyChildrenVa,
3225
+ _ref2$nodeAssign = _ref2.nodeAssign,
3226
+ nodeAssign = _ref2$nodeAssign === void 0 ? 'spread' : _ref2$nodeAssign;
3227
+
3228
+ /** @type {R[]} */
3229
+ var tree = [];
3230
+
3231
+ /** @type {Object.<string, T[]>} */
3232
+ var record = {};
3233
+ if (!Array.isArray(list)) {
3234
+ return tree;
3235
+ }
3236
+ list.forEach(function (item) {
3237
+ if (isObject(item)) {
3238
+ var newItem = nodeAssign === 'spread' ? _objectSpread2({}, item) : item;
3239
+
3240
+ /** @type {string} */
3241
+ var id = newItem[keyField];
3242
+
3243
+ /** @type {string} */
3244
+ var pid = newItem[parentField];
3245
+ if (record[id]) {
3246
+ // @ts-ignore
3247
+ newItem[childrenField] = record[id];
3248
+ } else {
3249
+ // @ts-ignore
3250
+ newItem[childrenField] = record[id] = [];
3251
+ }
3252
+ if (pid) {
3253
+ if (!record[pid]) {
3254
+ record[pid] = [newItem];
3255
+ } else {
3256
+ record[pid].push(newItem);
3257
+ }
3258
+ } else {
3259
+ // @ts-ignore
3260
+ tree.push(newItem);
3261
+ }
3262
+ }
3263
+ });
3264
+ if (emptyChildrenValue !== 'array') {
3265
+ // @ts-ignore
3266
+ processEmptyChildren(tree, options);
3267
+ }
3268
+ return tree;
3269
+ }
3270
+
3271
+ /**
3272
+ * 树结构转列表数据
3273
+ *
3274
+ * @static
3275
+ * @alias module:Tree.treeToList
3276
+ * @since 4.14.0
3277
+ * @template {Record<string,any>} T
3278
+ * @template {keyof T} K
3279
+ * @template {Omit<T, K>} R
3280
+ * @param {T[]} tree 列表数据
3281
+ * @param {K} childrenField 子级字段名称
3282
+ * @returns {R[]} 列表数据
3283
+ * @example
3284
+ * const menus = [{ "id": "1", "name": "首页", "code": "trade", "pid": null }, { "id": "2", "name": "交易管理", "code": "trade", "pid": null, "children": [{ "id": "3", "name": "交易查询", "code": "trade-1", "pid": "2", "children": [{ "id": "4", "name": "交易查询-查询操作", "code": "trade-1-1", "pid": "3" }] }] }, { "id": "5", "name": "权限管理", "code": "authorization", "pid": null, "children": [{ "id": "6", "name": "角色管理", "code": "authorization-1", "pid": "5" }, { "id": "7", "name": "用户管理", "code": "authorization-2", "pid": "5" }] }];
3285
+ *
3286
+ * treeToList(menus, 'children'));
3287
+ * // [{"id":"1","name":"首页","code":"trade","pid":null},{"id":"2","name":"交易管理","code":"trade","pid":null},{"id":"3","name":"交易查询","code":"trade-1","pid":"2"},{"id":"4","name":"交易查询-查询操作","code":"trade-1-1","pid":"3"},{"id":"5","name":"权限管理","code":"authorization","pid":null},{"id":"6","name":"角色管理","code":"authorization-1","pid":"5"},{"id":"7","name":"用户管理","code":"authorization-2","pid":"5"}]
3288
+ */
3289
+ function treeToList(tree, childrenField) {
3290
+ /** @type {R[]} */
3291
+ var list = [];
3292
+ if (!Array.isArray(tree)) {
3293
+ return list;
3294
+ }
3295
+
3296
+ /**
3297
+ * 递归遍历
3298
+ * @param {T[]} arr 列表数据
3299
+ */
3300
+ function recusion(arr) {
3301
+ arr.forEach(function (item) {
3302
+ if (isObject(item)) {
3303
+ var newItem = _objectSpread2({}, item);
3304
+ // @ts-ignore
3305
+ list.push(newItem);
3306
+ if (newItem[childrenField]) {
3307
+ if (Array.isArray(newItem[childrenField]) && newItem[childrenField].length > 0) {
3308
+ recusion(newItem[childrenField]);
3309
+ }
3310
+ delete newItem[childrenField];
3311
+ }
3312
+ } else {
3313
+ // @ts-ignore
3314
+ list.push(item);
3315
+ }
3316
+ });
3317
+ }
3318
+ recusion(tree);
3319
+ return list;
3320
+ }
3321
+
3322
+ /**
3323
+ * 过滤/筛选树节点。<br/><br/>如果某节点被过滤掉,它的子节点也一并抛弃
3324
+ *
3325
+ * @static
3326
+ * @alias module:Tree.filterTree
3327
+ * @since 4.15.0
3328
+ * @template {any} T
3329
+ * @template {(item: T) => boolean} F
3330
+ * @param {T[]} tree 树结构数据
3331
+ * @param {F} predicate 遍历每一项执行的函数,参数是当前遍历到的节点数据,如果返回 Truthy ,结果将包含该节点
3332
+ * @param {string} [childrenField='children'] 子级字段名
3333
+ * @param {'spread'|'self'} [nodeAssign='spread'] 节点赋值方式。spread表示使用展开运算符创建新值,self表示使用自身对象。
3334
+ * @returns {T[]}
3335
+ * @example
3336
+ * const menus = [{ "id": "1", "name": "首页", "code": "trade", "pid": null }, { "id": "2", "name": "交易管理", "code": "trade", "pid": null, "children": [{ "id": "3", "name": "交易查询", "code": "trade-1", "pid": "2", "children": [{ "id": "4", "name": "交易查询-查询操作", "code": "trade-1-1", "pid": "3" }] }] }, { "id": "5", "name": "权限管理", "code": "authorization", "pid": null, "children": [{ "id": "6", "name": "角色管理", "code": "authorization-1", "pid": "5" }, { "id": "7", "name": "用户管理", "code": "authorization-2", "pid": "5" }] }];
3337
+ *
3338
+ * filterTree(menus, item=>item.name.indexOf('管理') > -1);
3339
+ * // [{"id":"2","name":"交易管理","code":"trade","pid":null,"children":[]},{"id":"5","name":"权限管理","code":"authorization","pid":null,"children":[{"id":"6","name":"角色管理","code":"authorization-1","pid":"5"},{"id":"7","name":"用户管理","code":"authorization-2","pid":"5"}]}]
3340
+ *
3341
+ * // 如果某节点被过滤掉,它的子节点也一并抛弃
3342
+ * filterTree(menus, item=>item.id === '7');
3343
+ * // []
3344
+ *
3345
+ * filterTree(menus, item=>item.id === 'not found');
3346
+ * // []
3347
+ */
3348
+ function filterTree(tree, predicate) {
3349
+ var childrenField = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'children';
3350
+ var nodeAssign = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'spread';
3351
+ /** @type {T[]} */
3352
+ var result = [];
3353
+ if (!Array.isArray(tree)) {
3354
+ return result;
3355
+ }
3356
+ tree.forEach(function (item) {
3357
+ var newItem = item;
3358
+ if (isObject(item)) {
3359
+ // @ts-ignore
3360
+ newItem = nodeAssign === 'spread' ? _objectSpread2({}, item) : item;
3361
+ }
3362
+ if (predicate(newItem)) {
3363
+ if (isObject(newItem)) {
3364
+ /** @type {T[]|undefined} */
3365
+ // @ts-ignore
3366
+ var childs = newItem[childrenField];
3367
+ if (Array.isArray(childs) && childs.length > 0) {
3368
+ // @ts-ignore
3369
+ newItem[childrenField] = filterTree(childs, predicate, childrenField, nodeAssign);
3370
+ }
3371
+ }
3372
+ result.push(newItem);
3373
+ }
3374
+ });
3375
+ return result;
3376
+ }
3377
+
3374
3378
  /**
3375
3379
  * 查找树结构数据节点
3376
3380
  *
3377
3381
  * @static
3378
- * @alias module:Other.findTreeNode
3382
+ * @alias module:Tree.findTreeNode
3379
3383
  * @since 4.14.0
3380
3384
  * @template {any} T
3381
3385
  * @template {(item: T) => boolean} F
@@ -3443,7 +3447,7 @@
3443
3447
  * 查找树结构数据多个节点
3444
3448
  *
3445
3449
  * @static
3446
- * @alias module:Other.findTreeNodes
3450
+ * @alias module:Tree.findTreeNodes
3447
3451
  * @since 4.15.0
3448
3452
  * @template {any} T
3449
3453
  * @template {(item: T) => boolean} F
@@ -3557,7 +3561,7 @@
3557
3561
  * 查找包含当前节点的所有父级节点
3558
3562
  *
3559
3563
  * @static
3560
- * @alias module:Other.findTreeSelect
3564
+ * @alias module:Tree.findTreeSelect
3561
3565
  * @since 4.14.0
3562
3566
  * @template {any} T
3563
3567
  * @template {(item: T) => boolean} F