util-helpers 4.15.1 → 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.1";
540
+ var version = "4.15.3";
541
541
 
542
542
  /**
543
543
  * 打印警告信息
@@ -1897,25 +1897,25 @@
1897
1897
  * @alias module:Processor.formatMoney
1898
1898
  * @since 1.1.0
1899
1899
  * @param {string | number} num 需转换金额 (最大:9007199254740991 最小: -9007199254740991)
1900
- * @param {Object} [options] - 金额格式化配置
1901
- * @param {string | number} [options.precision=2] - 保留位数 (最高:10位)
1902
- * @param {string} [options.symbol] - 货币符号
1903
- * @param {string} [options.thousand=","] - 千分位符号
1904
- * @param {string} [options.decimal="."] - 小数位符号
1900
+ * @param {Object} [options] 金额格式化配置
1901
+ * @param {number} [options.precision=2] 保留位数 (最高:10位)
1902
+ * @param {string} [options.symbol] 货币符号
1903
+ * @param {string} [options.thousand=","] 千分位符号
1904
+ * @param {string} [options.decimal="."] 小数位符号
1905
1905
  * @returns {string} 格式化的金额
1906
1906
  * @example
1907
1907
  *
1908
1908
  * // 整数
1909
- * formatMoney('1000'); // 1,000.00
1909
+ * formatMoney(1000); // 1,000.00
1910
1910
  *
1911
1911
  * // 小数(默认保留2位小数)
1912
- * formatMoney('3000.03'); // 3,000.03
1912
+ * formatMoney(3000.03); // 3,000.03
1913
1913
  *
1914
1914
  * // 保留4位小数
1915
- * formatMoney('3000.0300', { precision: 4 }); // 3,000.0300
1915
+ * formatMoney(3000.03, { precision: 4 }); // 3,000.0300
1916
1916
  *
1917
1917
  * // 保留10位小数
1918
- * formatMoney('1500.2', { precision: 10 }); // 1,500.2000000000
1918
+ * formatMoney(1500.2, { precision: 10 }); // 1,500.2000000000
1919
1919
  *
1920
1920
  * // 自定义单位符号
1921
1921
  * formatMoney(1000.00, { symbol: '$' }); // $1,000.00
@@ -1926,6 +1926,8 @@
1926
1926
  * // 自定义小数位分割符(默认'.')
1927
1927
  * formatMoney(1000.00, { decimal: '&' }); // 1,000&00
1928
1928
  *
1929
+ * // 字符串数字
1930
+ * formatMoney('3000.03', { precision: 4 }); // 3,000.0300
1929
1931
  */
1930
1932
  var formatMoney = function formatMoney(num) {
1931
1933
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
@@ -2023,20 +2025,24 @@
2023
2025
  * @returns {string} 处理后的字符
2024
2026
  * @example
2025
2027
  *
2026
- * // 手机号
2028
+ * // 手机号 前3后4
2027
2029
  * replaceChar('13000000000'); // 130****0000
2028
2030
  *
2029
- * // 身份证
2030
- * replaceChar('130701199310302288'); // 130***********2288
2031
+ * // 身份证 前6后4
2032
+ * replaceChar('130701199310302288', { start: 6, end: -4 }); // 130701********2288
2031
2033
  *
2032
- * // 邮箱
2034
+ * // 邮箱 @前两位
2033
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位
2034
2039
  * replaceChar(email, {start: 2, end: email.indexOf('@'), repeat: 4}); // 12****@qq.com
2035
2040
  *
2036
- * // 银行卡号
2041
+ * // 银行卡号 只展示后4位,固定替换字符4位
2037
2042
  * replaceChar('6228480402564890018', {start: 0, end: -4, repeat: 4}); // ****0018
2038
- *
2039
- * // 带格式的银行卡号,忽略空字符串
2043
+ * // 银行卡号 前6后4
2044
+ * replaceChar('6228480402564890018', { start: 6, end: -4 }); // 622848*********0018
2045
+ * // 银行卡号 前4后3 忽略格式的空格
2040
2046
  * replaceChar('6228 4804 0256 4890 018', {start: 4, end: -4, exclude: ' '}); // 6228 **** **** **** 018
2041
2047
  *
2042
2048
  * // 用户名
@@ -2319,6 +2325,7 @@
2319
2325
  * @param {number} bytes 字节大小
2320
2326
  * @param {Object} [options] 配置项
2321
2327
  * @param {string} [options.spaceMark=' '] 间隔字符
2328
+ * @param {number} [options.precision=2] 精度
2322
2329
  * @returns {string} 存储单位值
2323
2330
  * @example
2324
2331
  *
@@ -2335,14 +2342,16 @@
2335
2342
  function bytesToSize(bytes) {
2336
2343
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2337
2344
  var _options$spaceMark = options.spaceMark,
2338
- spaceMark = _options$spaceMark === void 0 ? ' ' : _options$spaceMark;
2345
+ spaceMark = _options$spaceMark === void 0 ? ' ' : _options$spaceMark,
2346
+ _options$precision = options.precision,
2347
+ precision = _options$precision === void 0 ? 2 : _options$precision;
2339
2348
  var numBytes = typeof bytes !== 'number' ? Number(bytes) : bytes;
2340
2349
  if (numBytes === 0 || isNaN(numBytes)) return "0".concat(spaceMark, "B");
2341
2350
  var k = 1024;
2342
2351
  // 存储单位
2343
2352
  var sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
2344
2353
  var i = Math.floor(Math.log(numBytes) / Math.log(k));
2345
- return sizes[i] ? "".concat(Number((numBytes / Math.pow(k, i)).toFixed(2))).concat(spaceMark).concat(sizes[i]) : numBytes + '';
2354
+ return sizes[i] ? "".concat(Number((numBytes / Math.pow(k, i)).toFixed(precision))).concat(spaceMark).concat(sizes[i]) : numBytes + '';
2346
2355
  }
2347
2356
 
2348
2357
  var regIdCard = /*#__PURE__*/_wrapRegExp(/^(\d{2})(\d{2})(\d{2})((?:\d{2})?\d{2})(\d{2})(\d{2})\d{2}(\d)(?:\d|X)?$/i, {
@@ -2693,343 +2702,144 @@
2693
2702
  }
2694
2703
 
2695
2704
  /**
2696
- * 转换字段名,返回一个转换字段后的值,不改变原值。
2697
- *
2705
+ * 精确乘法,支持多个数相乘,乘数默认为 1 。
2706
+ *
2698
2707
  * @static
2699
- * @alias module:Processor.transformFieldNames
2700
- * @since 4.14.0
2701
- * @template {*} D
2702
- * @template {Record<string, keyof D>} F
2703
- * @template {string} C
2704
- * @param {D[]} data 对象数组。如果是树结构数据,需要指定第三个参数 childrenField
2705
- * @param {F} fieldNames 字段名映射
2706
- * @param {C} [childrenField] 子级数据字段名
2707
- * @param {'spread'|'self'} [nodeAssign='spread'] 节点赋值方式。spread表示使用展开运算符创建新值,self表示使用自身对象。
2708
- * @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} 乘积
2709
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
2710
2717
  *
2711
- * const options = [{code: '1', name: 'one'},{code:'2', name:'two'}];
2712
- * const newOptions = transformFieldNames(options, {label: 'name', value: 'code'});
2713
- * // [{value: '1', label: 'one'},{value:'2', label:'two'}]
2714
- *
2715
- * // 嵌套数据,指定子级字段名 children
2716
- * 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'}]}]}];
2717
- * const newOptions2 = transformFieldNames(options2, {label: 'name', value: 'code'}, 'children');
2718
- * // [{value: '1', label: 'one'},{value:'2', label:'two', children: [{value: '2-1', label:'two-one', children: [{value: '2-1-1', label:'two-one-one'}]}]}]
2719
- *
2720
- * const options3 = [{code: '1', name: 'one'},{code:'2', name:'two', childs: [{code:'2-1', name:'two-one'}]}];
2721
- * const newOptions3 = transformFieldNames(options3, {label: 'name', value: 'code'}, 'childs');
2722
- * // [{value: '1', label: 'one'},{value:'2', label:'two', childs: [{value: '2-1', label:'two-one'}]}]
2723
- *
2724
- * // 嵌套数据,并替换子集字段名
2725
- * const newOptions4 = transformFieldNames(options3, {label: 'name', value: 'code', children: 'childs'}, 'childs');
2726
- * // [{value: '1', label: 'one'},{value:'2', label:'two', children: [{value: '2-1', label:'two-one'}]}]
2727
2718
  */
2728
- function transformFieldNames(data, fieldNames, childrenField) {
2729
- var nodeAssign = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'spread';
2730
- if (!Array.isArray(data)) {
2731
- 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];
2732
2722
  }
2733
- if (data.length <= 0) {
2734
- // @ts-ignore
2735
- 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)));
2736
2729
  }
2730
+ num1 = transformEffectiveNumber(num1);
2731
+ num2 = transformEffectiveNumber(num2);
2737
2732
 
2738
- /**
2739
- * 递归处理字段名
2740
- *
2741
- * @param {Array.<object>} arr 列表数据
2742
- * @returns {*}
2743
- */
2744
- function recusion(arr) {
2745
- return arr.map(function (item) {
2746
- if (!isObject(item)) {
2747
- return item;
2748
- }
2749
- var newItem = nodeAssign === 'spread' ? _objectSpread2({}, item) : item;
2750
- /** @type {Array.<string>} */
2751
- var delKeys = [];
2752
-
2753
- // 树形数据子节点
2754
- // @ts-ignore
2755
- if (childrenField && Array.isArray(newItem[childrenField]) && newItem[childrenField].length > 0) {
2756
- // @ts-ignore
2757
- newItem[childrenField] = recusion(newItem[childrenField].slice());
2758
- }
2759
-
2760
- // 替换字段名
2761
- Object.keys(fieldNames).forEach(function (newKey) {
2762
- var oldKey = fieldNames[newKey];
2763
- if (oldKey in newItem) {
2764
- // @ts-ignore
2765
- newItem[newKey] = newItem[oldKey];
2766
- // @ts-ignore
2767
- delKeys.push(oldKey);
2768
- }
2769
- });
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
+ }
2770
2745
 
2771
- // 删除旧字段
2772
- if (delKeys.length > 0) {
2773
- delKeys.forEach(function (delKey) {
2774
- // @ts-ignore
2775
- delete newItem[delKey];
2776
- });
2777
- }
2778
- return newItem;
2779
- });
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];
2780
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);
2781
2774
 
2775
+ // 兼容处理,如果参数包含无效数值时,返回 NaN
2782
2776
  // @ts-ignore
2783
- 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;
2784
2782
  }
2785
2783
 
2786
2784
  /**
2787
- * 递归处理空子级
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
2788
2797
  *
2789
- * @private
2790
- * @template {Record<string,any>} [T=Record<string,any>]
2791
- * @param {T[]} arr 列表数据
2792
- * @param {object} [options] 配置项
2793
- * @param {string} [options.childrenField='children'] 子级字段名称
2794
- * @param {'none'|'null'} [options.emptyChildrenValue='none'] 子级为空时的值,none表示删除该子级,null表示为null,array表示为[]。
2795
2798
  */
2796
- function processEmptyChildren(arr, options) {
2797
- var _ref = options || {},
2798
- _ref$childrenField = _ref.childrenField,
2799
- childrenField = _ref$childrenField === void 0 ? 'children' : _ref$childrenField,
2800
- _ref$emptyChildrenVal = _ref.emptyChildrenValue,
2801
- emptyChildrenValue = _ref$emptyChildrenVal === void 0 ? 'none' : _ref$emptyChildrenVal;
2802
- arr.forEach(function (item) {
2803
- // if (isObject(item) && Array.isArray(item[childrenField])) {
2804
- if (item[childrenField].length <= 0) {
2805
- if (emptyChildrenValue === 'null') {
2806
- // @ts-ignore
2807
- item[childrenField] = null;
2808
- // } else if (emptyChildrenValue === 'none') { // emptyChildrenValue='array' 不会执行该内部方法
2809
- } else {
2810
- delete item[childrenField];
2811
- }
2812
- } else {
2813
- processEmptyChildren(item[childrenField], options);
2814
- }
2815
- // }
2816
- });
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;
2817
2820
  }
2818
2821
 
2819
2822
  /**
2820
- * 列表数据转树结构
2821
- *
2823
+ * 精确除法,支持多个数相除,除数默认为 1 。
2824
+ *
2822
2825
  * @static
2823
- * @alias module:Processor.listToTree
2824
- * @since 4.14.0
2825
- * @template {Record<string,any>} [T=Record<string,any>]
2826
- * @template {*} [R=T&Record<string,any>]
2827
- * @param {T[]} list 列表数据
2828
- * @param {object} [options] 配置项
2829
- * @param {string} [options.keyField='id'] 当前数据的键值字段名称
2830
- * @param {string} [options.parentField='pid'] 当前数据的父级字段名称
2831
- * @param {string} [options.childrenField='children'] 子级字段名称
2832
- * @param {'none'|'null'|'array'} [options.emptyChildrenValue='none'] 子级为空时的值,none表示删除该子级,null表示为null,array表示为[]。
2833
- * @param {'spread'|'self'} [options.nodeAssign='spread'] 节点赋值方式。spread表示使用展开运算符创建新值,self表示使用自身对象。
2834
- * @returns {R[]} 树结构
2826
+ * @alias module:Math.divide
2827
+ * @since 3.1.0
2828
+ * @param {...number|string} nums 被除数和除数
2829
+ * @returns {number} 商数
2835
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
2836
2836
  *
2837
- * const menus = [
2838
- * { id: '1', name: '首页', code: 'trade', pid: null },
2839
- * { id: '2', name: '交易管理', code: 'trade', pid: null },
2840
- * { id: '3', name: '交易查询', code: 'trade-1', pid: '2' },
2841
- * { id: '4', name: '交易查询-查询操作', code: 'trade-1-1', pid: '3' },
2842
- * { id: '5', name: '权限管理', code: 'authorization', pid: null },
2843
- * { id: '6', name: '角色管理', code: 'authorization-1', pid: '5' },
2844
- * { id: '7', name: '用户管理', code: 'authorization-2', pid: '5' }
2845
- * ];
2846
- * listToTree(menus);
2847
- * // [{"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"}]}]
2848
- *
2849
- * // 自定义子级字段名
2850
- * listToTree(basicMenus, { childrenField: 'childs' });
2851
- * // [{"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
2852
2840
  *
2853
2841
  */
2854
- function listToTree(list, options) {
2855
- var _ref2 = options || {},
2856
- _ref2$keyField = _ref2.keyField,
2857
- keyField = _ref2$keyField === void 0 ? 'id' : _ref2$keyField,
2858
- _ref2$parentField = _ref2.parentField,
2859
- parentField = _ref2$parentField === void 0 ? 'pid' : _ref2$parentField,
2860
- _ref2$childrenField = _ref2.childrenField,
2861
- childrenField = _ref2$childrenField === void 0 ? 'children' : _ref2$childrenField,
2862
- _ref2$emptyChildrenVa = _ref2.emptyChildrenValue,
2863
- emptyChildrenValue = _ref2$emptyChildrenVa === void 0 ? 'none' : _ref2$emptyChildrenVa,
2864
- _ref2$nodeAssign = _ref2.nodeAssign,
2865
- nodeAssign = _ref2$nodeAssign === void 0 ? 'spread' : _ref2$nodeAssign;
2866
-
2867
- /** @type {R[]} */
2868
- var tree = [];
2869
-
2870
- /** @type {Object.<string, T[]>} */
2871
- var record = {};
2872
- if (!Array.isArray(list)) {
2873
- return tree;
2874
- }
2875
- list.forEach(function (item) {
2876
- if (isObject(item)) {
2877
- var newItem = nodeAssign === 'spread' ? _objectSpread2({}, item) : item;
2878
-
2879
- /** @type {string} */
2880
- var id = newItem[keyField];
2881
-
2882
- /** @type {string} */
2883
- var pid = newItem[parentField];
2884
- if (record[id]) {
2885
- // @ts-ignore
2886
- newItem[childrenField] = record[id];
2887
- } else {
2888
- // @ts-ignore
2889
- newItem[childrenField] = record[id] = [];
2890
- }
2891
- if (pid) {
2892
- if (!record[pid]) {
2893
- record[pid] = [newItem];
2894
- } else {
2895
- record[pid].push(newItem);
2896
- }
2897
- } else {
2898
- // @ts-ignore
2899
- tree.push(newItem);
2900
- }
2901
- }
2902
- });
2903
- if (emptyChildrenValue !== 'array') {
2904
- // @ts-ignore
2905
- processEmptyChildren(tree, options);
2906
- }
2907
- return tree;
2908
- }
2909
-
2910
- /**
2911
- * 树结构转列表数据
2912
- *
2913
- * @static
2914
- * @alias module:Processor.treeToList
2915
- * @since 4.14.0
2916
- * @template {Record<string,any>} T
2917
- * @template {keyof T} K
2918
- * @template {Omit<T, K>} R
2919
- * @param {T[]} tree 列表数据
2920
- * @param {K} childrenField 子级字段名称
2921
- * @returns {R[]} 列表数据
2922
- * @example
2923
- * 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" }] }];
2924
- *
2925
- * treeToList(menus, 'children'));
2926
- * // [{"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"}]
2927
- */
2928
- function treeToList(tree, childrenField) {
2929
- /** @type {R[]} */
2930
- var list = [];
2931
- if (!Array.isArray(tree)) {
2932
- return list;
2933
- }
2934
-
2935
- /**
2936
- * 递归遍历
2937
- * @param {T[]} arr 列表数据
2938
- */
2939
- function recusion(arr) {
2940
- arr.forEach(function (item) {
2941
- if (isObject(item)) {
2942
- var newItem = _objectSpread2({}, item);
2943
- // @ts-ignore
2944
- list.push(newItem);
2945
- if (newItem[childrenField]) {
2946
- if (Array.isArray(newItem[childrenField]) && newItem[childrenField].length > 0) {
2947
- recusion(newItem[childrenField]);
2948
- }
2949
- delete newItem[childrenField];
2950
- }
2951
- } else {
2952
- // @ts-ignore
2953
- list.push(item);
2954
- }
2955
- });
2956
- }
2957
- recusion(tree);
2958
- return list;
2959
- }
2960
-
2961
- /**
2962
- * 过滤/筛选树节点。<br/><br/>如果某节点被过滤掉,它的子节点也一并抛弃
2963
- *
2964
- * @static
2965
- * @alias module:Processor.filterTree
2966
- * @since 4.15.0
2967
- * @template {any} T
2968
- * @template {(item: T) => boolean} F
2969
- * @param {T[]} tree 树结构数据
2970
- * @param {F} predicate 遍历每一项执行的函数,参数是当前遍历到的节点数据,如果返回 Truthy ,结果将包含该节点
2971
- * @param {string} [childrenField='children'] 子级字段名
2972
- * @param {'spread'|'self'} [nodeAssign='spread'] 节点赋值方式。spread表示使用展开运算符创建新值,self表示使用自身对象。
2973
- * @returns {T[]}
2974
- * @example
2975
- * 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" }] }];
2976
- *
2977
- * filterTree(menus, item=>item.name.indexOf('管理') > -1);
2978
- * // [{"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"}]}]
2979
- *
2980
- * // 如果某节点被过滤掉,它的子节点也一并抛弃
2981
- * filterTree(menus, item=>item.id === '7');
2982
- * // []
2983
- *
2984
- * filterTree(menus, item=>item.id === 'not found');
2985
- * // []
2986
- */
2987
- function filterTree(tree, predicate) {
2988
- var childrenField = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'children';
2989
- var nodeAssign = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'spread';
2990
- /** @type {T[]} */
2991
- var result = [];
2992
- if (!Array.isArray(tree)) {
2993
- return result;
2994
- }
2995
- tree.forEach(function (item) {
2996
- var newItem = item;
2997
- if (isObject(item)) {
2998
- // @ts-ignore
2999
- newItem = nodeAssign === 'spread' ? _objectSpread2({}, item) : item;
3000
- }
3001
- if (predicate(newItem)) {
3002
- if (isObject(newItem)) {
3003
- /** @type {T[]|undefined} */
3004
- // @ts-ignore
3005
- var childs = newItem[childrenField];
3006
- if (Array.isArray(childs) && childs.length > 0) {
3007
- // @ts-ignore
3008
- newItem[childrenField] = filterTree(childs, predicate, childrenField, nodeAssign);
3009
- }
3010
- }
3011
- result.push(newItem);
3012
- }
3013
- });
3014
- return result;
3015
- }
3016
-
3017
- /**
3018
- * 精确乘法,支持多个数相乘,乘数默认为 1 。
3019
- *
3020
- * @static
3021
- * @alias module:Math.times
3022
- * @since 3.1.0
3023
- * @param {...number|string} nums 相乘的数
3024
- * @returns {number} 乘积
3025
- * @example
3026
- *
3027
- * times(3, 0.6); // 1.8
3028
- * times(3, 0.6, 2); // 3.6
3029
- * times(3, 0.6, 2, 10); // 36
3030
- *
3031
- */
3032
- function times() {
2842
+ function divide() {
3033
2843
  for (var _len = arguments.length, nums = new Array(_len), _key = 0; _key < _len; _key++) {
3034
2844
  nums[_key] = arguments[_key];
3035
2845
  }
@@ -3038,7 +2848,7 @@
3038
2848
  num2 = _nums$ === void 0 ? 1 : _nums$,
3039
2849
  rest = nums.slice(2);
3040
2850
  if (rest.length > 0) {
3041
- return times.apply(void 0, [times(num1, num2)].concat(_toConsumableArray(rest)));
2851
+ return divide.apply(void 0, [divide(num1, num2)].concat(_toConsumableArray(rest)));
3042
2852
  }
3043
2853
  num1 = transformEffectiveNumber(num1);
3044
2854
  num2 = transformEffectiveNumber(num2);
@@ -3050,190 +2860,67 @@
3050
2860
  }
3051
2861
  var num1Changed = float2Fixed(num1);
3052
2862
  var num2Changed = float2Fixed(num2);
3053
- var baseNum = digitLength(num1) + digitLength(num2);
3054
- var leftValue = num1Changed * num2Changed;
3055
- checkBoundary(leftValue);
3056
- 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))));
3057
2867
  }
3058
2868
 
3059
2869
  /**
3060
- * 精确加法,支持多个数相加,加数默认为 0 。
2870
+ * 四舍五入,支持设置精度
3061
2871
  *
3062
2872
  * @static
3063
- * @alias module:Math.plus
2873
+ * @alias module:Math.round
3064
2874
  * @since 3.1.0
3065
- * @param {...number|string} nums 相加的数
3066
- * @returns {number} 总和
2875
+ * @param {number|string} num 要四舍五入的数字
2876
+ * @param {number} [precision=0] 四舍五入的精度
2877
+ * @returns {number} 四舍五入的数字
3067
2878
  * @example
3068
2879
  *
3069
- * plus(0.1, 0.2); // 0.3
3070
- * plus(0.1, 0.2, 0.3); // 0.6
3071
- * 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
3072
2883
  *
3073
2884
  */
3074
- function plus() {
3075
- for (var _len = arguments.length, nums = new Array(_len), _key = 0; _key < _len; _key++) {
3076
- nums[_key] = arguments[_key];
3077
- }
3078
- var num1 = nums[0],
3079
- _nums$ = nums[1],
3080
- num2 = _nums$ === void 0 ? 0 : _nums$,
3081
- rest = nums.slice(2);
3082
- if (rest.length > 0) {
3083
- return plus.apply(void 0, [plus(num1, num2)].concat(_toConsumableArray(rest)));
3084
- }
3085
- num1 = transformEffectiveNumber(num1);
3086
- num2 = transformEffectiveNumber(num2);
2885
+ function round(num) {
2886
+ var precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
2887
+ num = transformEffectiveNumber(num);
3087
2888
 
3088
2889
  // 兼容处理,如果参数包含无效数值时,返回 NaN
3089
2890
  // @ts-ignore
3090
- if (isNaN(num1) || isNaN(num2)) {
2891
+ if (isNaN(num)) {
3091
2892
  return Number.NaN;
3092
2893
  }
3093
- var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
3094
- return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
2894
+ var base = Math.pow(10, precision);
2895
+ return divide(Math.round(times(num, base)), base);
3095
2896
  }
3096
2897
 
3097
2898
  /**
3098
- * 精确减法,支持多个数相减,减数默认为 0
2899
+ * 等待时间返回 Promise 。常用于异步方法中延时。
3099
2900
  *
3100
2901
  * @static
3101
- * @alias module:Math.minus
3102
- * @since 3.1.0
3103
- * @param {...number|string} nums 相减的数
3104
- * @returns {number}
2902
+ * @alias module:Other.waitTime
2903
+ * @since 4.2.0
2904
+ * @param {number} [time=1000] 延时时间,单位毫秒
2905
+ * @returns {Promise<void>}
3105
2906
  * @example
2907
+ *
2908
+ * const test = async ()=>{
2909
+ * await waitTime();
2910
+ * // do something
2911
+ * }
3106
2912
  *
3107
- * minus(1, 0.9); // 0.1
3108
- * minus(1, 0.9, 0.02); // 0.08
3109
- * minus(1, 0.9, 0.02, 0.08); // 0
2913
+ * waitTime(500).then(()=>{
2914
+ * // do something
2915
+ * });
3110
2916
  *
3111
2917
  */
3112
- function minus() {
3113
- for (var _len = arguments.length, nums = new Array(_len), _key = 0; _key < _len; _key++) {
3114
- nums[_key] = arguments[_key];
3115
- }
3116
- var num1 = nums[0],
3117
- _nums$ = nums[1],
3118
- num2 = _nums$ === void 0 ? 0 : _nums$,
3119
- rest = nums.slice(2);
3120
- if (rest.length > 0) {
3121
- return minus.apply(void 0, [minus(num1, num2)].concat(_toConsumableArray(rest)));
3122
- }
3123
- num1 = transformEffectiveNumber(num1);
3124
- num2 = transformEffectiveNumber(num2);
3125
-
3126
- // 兼容处理,如果参数包含无效数值时,返回 NaN
3127
- // @ts-ignore
3128
- if (isNaN(num1) || isNaN(num2)) {
3129
- return Number.NaN;
3130
- }
3131
- var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
3132
- return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
3133
- }
3134
-
3135
- /**
3136
- * 精确除法,支持多个数相除,除数默认为 1 。
3137
- *
3138
- * @static
3139
- * @alias module:Math.divide
3140
- * @since 3.1.0
3141
- * @param {...number|string} nums 被除数和除数
3142
- * @returns {number} 商数
3143
- * @example
3144
- *
3145
- * divide(1.21); // 1.21 除数默认为 1 ,即 1.21/1 = 1.21
3146
- * divide(1.21, 1.1); // 1.1
3147
- * divide(1000, 10, 10); // 10
3148
- * divide(1000, 10, 10, 10); // 1
3149
- *
3150
- * divide(); // NaN 如果没有传入参数,被除数默认为 undefined 。 Number(undefined) 转换为 NaN ,NaN/1 = NaN
3151
- * divide(null); // 0 Number(null) 转换为 0 , 0/1 = 0
3152
- * divide('1.5 ', 0.5); // 3 Number('1.5 ') 转换为 1.5 ,1.5/0.5 = 3
3153
- *
3154
- */
3155
- function divide() {
3156
- for (var _len = arguments.length, nums = new Array(_len), _key = 0; _key < _len; _key++) {
3157
- nums[_key] = arguments[_key];
3158
- }
3159
- var num1 = nums[0],
3160
- _nums$ = nums[1],
3161
- num2 = _nums$ === void 0 ? 1 : _nums$,
3162
- rest = nums.slice(2);
3163
- if (rest.length > 0) {
3164
- return divide.apply(void 0, [divide(num1, num2)].concat(_toConsumableArray(rest)));
3165
- }
3166
- num1 = transformEffectiveNumber(num1);
3167
- num2 = transformEffectiveNumber(num2);
3168
-
3169
- // 兼容处理,如果参数包含无效数值时,返回 NaN
3170
- // @ts-ignore
3171
- if (isNaN(num1) || isNaN(num2)) {
3172
- return Number.NaN;
3173
- }
3174
- var num1Changed = float2Fixed(num1);
3175
- var num2Changed = float2Fixed(num2);
3176
- checkBoundary(num1Changed);
3177
- checkBoundary(num2Changed);
3178
- // fix: 类似 10 ** -4 为 0.00009999999999999999,strip 修正
3179
- return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1))));
3180
- }
3181
-
3182
- /**
3183
- * 四舍五入,支持设置精度
3184
- *
3185
- * @static
3186
- * @alias module:Math.round
3187
- * @since 3.1.0
3188
- * @param {number|string} num 要四舍五入的数字
3189
- * @param {number} [precision=0] 四舍五入的精度
3190
- * @returns {number} 四舍五入的数字
3191
- * @example
3192
- *
3193
- * round(4.006); // 4
3194
- * round(4.006, 2); // 4.01
3195
- * round(4060, -2); // 4100
3196
- *
3197
- */
3198
- function round(num) {
3199
- var precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
3200
- num = transformEffectiveNumber(num);
3201
-
3202
- // 兼容处理,如果参数包含无效数值时,返回 NaN
3203
- // @ts-ignore
3204
- if (isNaN(num)) {
3205
- return Number.NaN;
3206
- }
3207
- var base = Math.pow(10, precision);
3208
- return divide(Math.round(times(num, base)), base);
3209
- }
3210
-
3211
- /**
3212
- * 等待时间返回 Promise 。常用于异步方法中延时。
3213
- *
3214
- * @static
3215
- * @alias module:Other.waitTime
3216
- * @since 4.2.0
3217
- * @param {number} [time=1000] 延时时间,单位毫秒
3218
- * @returns {Promise<void>}
3219
- * @example
3220
- *
3221
- * const test = async ()=>{
3222
- * await waitTime();
3223
- * // do something
3224
- * }
3225
- *
3226
- * waitTime(500).then(()=>{
3227
- * // do something
3228
- * });
3229
- *
3230
- */
3231
- function waitTime() {
3232
- var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1000;
3233
- return new Promise(function (resolve) {
3234
- setTimeout(resolve, time);
3235
- });
3236
- }
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
+ }
3237
2924
 
3238
2925
  // ref: https://github.com/ant-design/ant-design-mobile/blob/v2/components/input-item/index.tsx#L240
3239
2926
 
@@ -3366,11 +3053,333 @@
3366
3053
  return len;
3367
3054
  }
3368
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
+
3369
3378
  /**
3370
3379
  * 查找树结构数据节点
3371
3380
  *
3372
3381
  * @static
3373
- * @alias module:Other.findTreeNode
3382
+ * @alias module:Tree.findTreeNode
3374
3383
  * @since 4.14.0
3375
3384
  * @template {any} T
3376
3385
  * @template {(item: T) => boolean} F
@@ -3438,7 +3447,7 @@
3438
3447
  * 查找树结构数据多个节点
3439
3448
  *
3440
3449
  * @static
3441
- * @alias module:Other.findTreeNodes
3450
+ * @alias module:Tree.findTreeNodes
3442
3451
  * @since 4.15.0
3443
3452
  * @template {any} T
3444
3453
  * @template {(item: T) => boolean} F
@@ -3552,7 +3561,7 @@
3552
3561
  * 查找包含当前节点的所有父级节点
3553
3562
  *
3554
3563
  * @static
3555
- * @alias module:Other.findTreeSelect
3564
+ * @alias module:Tree.findTreeSelect
3556
3565
  * @since 4.14.0
3557
3566
  * @template {any} T
3558
3567
  * @template {(item: T) => boolean} F