JavaScript通用方法汇总

本文介绍了多个数据处理函数,包括将数据转换为树结构、金额格式化、金额转中文、解决JS精度问题的相加操作、生成64进制ID以及重置分支点编号。这些函数适用于数据转换和计算场景,特别是涉及树形结构数据的操作。
摘要由CSDN通过智能技术生成

目录

ToTree树结构数据转换

金额格式化

金额转中文

JS相加处理精度问题

根据自增数生成64进制id

重置分支点编号(适应于有子级,中间可随意添加节点的分支结构)


ToTree树结构数据转换

// 将数据集合转换为树形结构
function toTree({ arrayList, pidStr = 'parentId', idStr = 'id', childrenStr = 'children' }) {
  const listOjb = {}; // 用来储存{key: obj}格式的对象
  const treeList = []; // 用来储存最终树形结构数据的数组
  // 将数据变换成{key: obj}格式,方便下面处理数据
  for (let i = 0; i < arrayList.length; i++) {
    listOjb[arrayList[i][idStr]] = arrayList[i];
  }
  // 根据pid来将数据进行格式化
  for (let j = 0; j < arrayList.length; j++) {
    // 判断父级是否存在
    const haveParent = listOjb[arrayList[j][pidStr]];
    if (haveParent) {
      // 如果有没有父级children字段,就创建一个children字段
      !haveParent[childrenStr] && (haveParent[childrenStr] = []);
      // 在父级里插入子项
      haveParent[childrenStr].push(arrayList[j]);
    } else {
      // 如果没有父级直接插入到最外层
      treeList.push(arrayList[j]);
    }
  }
  return treeList;
}

金额格式化

/*
 * 金额格式化:
 * number:要格式化的数字
 * decimals:保留几位小数
 * tdecPoint:小数点符号
 * thousandsSep:千分位符号
 * */
function numberFormat(number, decimals = 2, tdecPoint = '.', thousandsSep = ',') {
  number = (number + '').replace(/[^0-9+-Ee.]/g, '');
  if (number.indexOf(',') > -1) {
    return number;
  }
  let n = !isFinite(+number) ? 0 : +number,
    prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
    sep = typeof thousandsSep === 'undefined' ? ',' : thousandsSep,
    dec = typeof tdecPoint === 'undefined' ? '.' : tdecPoint,
    s = '',
    toFixedFix = function(n, prec) {
      const k = Math.pow(10, prec);
      return '' + Math.ceil(n * k) / k;
    };

  s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
  const re = /(-?\d+)(\d{3})/;
  while (re.test(s[0])) {
    s[0] = s[0].replace(re, '$1' + sep + '$2');
  }

  if ((s[1] || '').length < prec) {
    s[1] = s[1] || '';
    s[1] += new Array(prec - s[1].length + 1).join('0');
  }
  return s.join(dec);
}

金额转中文

function getAmountChinese(val) {
  const amount = +val
  if (Number.isNaN(amount) || amount < 0) return ''
  const NUMBER = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
  const N_UNIT1 = ['', '拾', '佰', '仟']
  const N_UNIT2 = ['', '万', '亿']
  const D_UNIT = ['角', '分', '厘', '毫']
  let [integer, decimal] = amount.toString().split('.')
  if (integer && integer.length > 12) return '金额过大无法计算'
  let res = ''
  // 整数部分
  if (integer) {
    for (let i = 0, len = integer.length; i < len; i++) {
      const num = integer.charAt(i)
      const pos = len - i - 1 // 排除个位后 所处的索引位置
      if (num === '0') { // 当前位 等于 0 且下一位也等于 0 则可跳过计算
        if (i === len - 1) {
          if (integer.length === 1) res += '零'  // 0.35 这种情况不可跳过计算
          break
        }
        if (integer.charAt(i + 1) === '0') continue
      }
      res += NUMBER[num]
      if (parseInt(num)) res += N_UNIT1[(pos) % 4]
      if (pos % 4 === 0) res += N_UNIT2[Math.floor(pos / 4)]
    }
  }
  res += '圆'
  // 小数部分
  if (parseInt(decimal)) {
    for (let i = 0; i < 4; i++) {
      const num = decimal.charAt(i)
      if (parseInt(num)) res += NUMBER[num] + D_UNIT[i]
    }
  } else {
    res += '整'
  }
  return res
}

JS相加处理精度问题

/** js数值计算,避免精度丢失,先扩大倍数,再缩小位数
 *  示例:accAdd(1,2,3.01)
 */
function accAdd() {
  if (arguments.length === 0) return 0;
  const list = [];
  // 获取小数位最大精度
  // for (const item of arguments) {
  //   let tem = 0;
  //   try {
  //     if (tem) {
  //       tem = item.toString().split('.')[1].length;
  //     }
  //   } catch (e) {
  //     tem = 0;
  //   }
  //   list.push(tem);
  // }
  // 计算最大数度值,避免精度丢失,先扩大位数,再缩小
  // const mPow = Math.pow(10, Math.max(...list));
  const mPow = 100; // 默认2位小数
  let total = 0;
  for (const item of arguments) {
    let tem = 0;
    if (item) {
      tem = parseFloat(item) ?? 0; // parseFloat处理,转化失败时给0
    }
    total += tem * mPow;
  }
  // toFixed部分浏览器会用问题,toFixed它是一个四舍六入五成双的诡异的方法(也叫银行家算法),"四舍六入五成双"含义:对于位数很多的近似数,当有效位数确定后,其后面多余的数字应该舍去,只保留有效数字最末一位,这种修约(舍入)规则是“四舍六入五成双”,也即“4舍6入5凑偶”这里“四”是指≤4 时舍去,"六"是指≥6时进上,"五"指的是根据5后面的数字来定,当5后有数时,舍5入1;当5后无有效数字时,需要分两种情况来讲:①5前为奇数,舍5入1;②5前为偶数,舍5不进。(0是偶数)
  const res = (total / mPow).toFixed(2);
  // // 修复toFixed
  // const res = parseInt(total + 0.5, 10) / times;

  return res;
}

根据自增数生成64进制id

  /**
   * 根据自增数生成64进制id
   * @returns 64进制id字符串
   */
    function idGenerator() {
        let qutient = (new Date() - new Date('2021-12-05'))
        qutient += Math.ceil(Math.random() * 1000) // 防止重複
        const chars = '0123456789ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz';
        const charArr = chars.split("")
        const radix = chars.length;
        const res = []
        do {
            let mod = qutient % radix;
            qutient = (qutient - mod) / radix;
            res.push(charArr[mod])
        } while (qutient);
        return res.join('')
    }

重置分支点编号(适应于有子级,中间可随意添加节点的分支结构)

    /** 重置节点编号,因为中间可以添加、删除节点,导致节点的previd不准确 */
    function reSetFlowNodeId(json) {
        function shiftNodeId(item, pid) {
            const id =idGenerator() // 此处调用随机不重复64进制id方法
            item.nodeId = id
            item.prevId = pid
            if (item.childNode) {
                shiftNodeId(item.childNode, item.nodeId)
            }
            if (item.conditionNodes) {
                item.conditionNodes.forEach((element) => {
                    shiftNodeId(element, item.nodeId)
                })
            }
            return item
        }
        return shiftNodeId(json, 0)
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值