money.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /**
  2. * 金额转换
  3. * @param money 金额
  4. * @param config
  5. * @param config.type 类型 full | number | unit
  6. * @param config.level 初始单位索引
  7. * @param config.levelArr 单位数组 ['元', '万', '亿', '万亿']
  8. * @param config.unit 计算单位 10000
  9. * @param config.digit 精度,保留小数位数 2
  10. * @param config.degrade 指定单位索引时,所需精度不够是否降级单位 false
  11. * @returns {*|string|string|number}
  12. */
  13. function recursiveCalculationMoney(money, config = {}, start = false) {
  14. const { type, level, levelArr, unit, digit, degrade } = Object.assign(
  15. {
  16. type: 'full',
  17. level: 0,
  18. levelArr: ['元', '万元', '亿元', '万亿元'],
  19. digit: 2,
  20. degrade: false,
  21. unit: 10000
  22. },
  23. config
  24. )
  25. // 提取纯数字
  26. let computMoney = String(money).match(/^\d+(\.\d+)?/g) || [0]
  27. computMoney = Number(computMoney[0])
  28. // 是否指定单位索引
  29. const lockUnit = start && level > 0
  30. // 判断是否需要递归单位
  31. if (!lockUnit) {
  32. const canNext =
  33. computMoney / Math.pow(unit, level + 1) >= 1 &&
  34. level + 1 < levelArr.length
  35. if (canNext) {
  36. return recursiveCalculationMoney(computMoney, {
  37. type,
  38. level: level + 1,
  39. levelArr,
  40. digit,
  41. degrade,
  42. unit
  43. })
  44. }
  45. }
  46. // 浮点数精度
  47. const digitNumber = Math.pow(10, digit)
  48. // 指定单位索引时,如不满足精度要求,是否需要降级单位处理
  49. let computLevel = level
  50. const needDegrade =
  51. degrade && computMoney * digitNumber < Math.pow(unit, level)
  52. if (lockUnit && needDegrade) {
  53. computLevel--
  54. }
  55. // 计算金额
  56. const addPowMoney = Math.floor(
  57. Number(
  58. ((computMoney / Math.pow(unit, computLevel)) * digitNumber).toPrecision(
  59. 12
  60. )
  61. )
  62. )
  63. const resetPowMoney = Number((addPowMoney / digitNumber).toPrecision(12))
  64. computMoney = resetPowMoney
  65. // 返回结果
  66. switch (type) {
  67. case 'full': {
  68. if (computMoney === 0) {
  69. return ''
  70. } else {
  71. return computMoney + levelArr[computLevel]
  72. }
  73. }
  74. case 'unit': {
  75. return levelArr[computLevel]
  76. }
  77. case 'number': {
  78. return computMoney
  79. }
  80. }
  81. }
  82. /**
  83. * 金额转换
  84. * @param money 金额
  85. * @param config
  86. * @param config.type 类型 full | number | unit
  87. * @param config.level 初始单位索引
  88. * @param config.levelArr 单位数组 ['元', '万元', '亿元', '万亿元']
  89. * @param config.unit 计算单位 10000
  90. * @param config.digit 精度,保留小数位数 2
  91. * @param config.degrade 指定单位索引时,所需精度不够是否降级单位 false
  92. * @returns {*|string|string|number}
  93. */
  94. export function formatMoney(money, config = {}) {
  95. if (config.level === 1 && !config.degrade) {
  96. // 万元单位, 并且不单位降级, 则小于100元的金额会被舍弃, 造成显示空白
  97. // 此处逻辑: 单位固定万元,不降级. 金额<10000, 展示元为单位
  98. if (money && money > 0 && money < 10000) {
  99. return `${money}元`
  100. } else {
  101. return recursiveCalculationMoney(money, config, true)
  102. }
  103. } else {
  104. return recursiveCalculationMoney(money, config, true)
  105. }
  106. }
  107. /**
  108. * 金额浮点问题修复
  109. * @param number
  110. * @returns {number}
  111. */
  112. export function formatNumber(number) {
  113. return Number(number.toFixed(12))
  114. }
  115. // 元转分
  116. export function yuan2Fen(v) {
  117. return formatNumber((v * 10000) / 100)
  118. }
  119. // 金额3位逗号分隔 ------------>
  120. /**
  121. * @param s 要格式化的数字(四舍五入)
  122. * @param n 保留几位小数(不传或者传-1 --> 如果为整数,则不保留小数。如果为浮点数,则保留两位小数)
  123. * @param comma 是否小数点前每3位添加逗号
  124. */
  125. export function splitMoney(s = 0, n = -1, comma = false) {
  126. n = n === -1 ? 0 : n
  127. if (n > 20 || n < -1) {
  128. n = 2
  129. }
  130. s = Number(s)
  131. return s.toLocaleString('zh-CN', {
  132. style: 'decimal',
  133. useGrouping: comma,
  134. minimumFractionDigits: n,
  135. maximumFractionDigits: n
  136. })
  137. }