时空网前端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 lines
3.1 KiB

4 years ago
  1. <template>
  2. <text class="md-amount" :class="{numerical: !isCapital}">
  3. <text v-if="!isCapital">{{ formatValue | doPrecision(legalPrecision, isRoundUp) | doFormat(hasSeparator, separator) }}</text>
  4. <text v-else> {{ formatValue | doPrecision(4, isRoundUp) | doCapital }} </text>
  5. </text>
  6. </template>
  7. <script> import {noop, inBrowser} from './_util'
  8. import Animate from './_util/animate'
  9. import {formatValueByGapStep} from './_util/formate-value'
  10. import numberCapital from './number-capital'
  11. export default {
  12. name: 'md-amount',
  13. filters: {
  14. doPrecision(value, precision, isRoundUp) {
  15. const exponentialForm = Number(`${value}e${precision}`)
  16. const rounded = isRoundUp ? Math.round(exponentialForm) : Math.floor(exponentialForm)
  17. return Number(`${rounded}e-${precision}`).toFixed(precision)
  18. },
  19. doFormat(value, hasSeparator, separator) {
  20. if (!hasSeparator) {
  21. return value
  22. }
  23. const numberParts = value.split('.')
  24. const integerValue = numberParts[0]
  25. const decimalValue = numberParts[1] || ''
  26. const formateValue = formatValueByGapStep(3, integerValue, separator, 'right', 0, 1)
  27. return decimalValue ? `${formateValue.value}.${decimalValue}` : `${formateValue.value}`
  28. },
  29. doCapital(value) {
  30. return numberCapital(value)
  31. },
  32. },
  33. props: {
  34. value: {
  35. type: Number,
  36. default: 0,
  37. },
  38. precision: {
  39. type: Number,
  40. default: 2,
  41. },
  42. isRoundUp: {
  43. type: Boolean,
  44. default: true,
  45. },
  46. hasSeparator: {
  47. type: Boolean,
  48. default: false,
  49. },
  50. separator: {
  51. type: String,
  52. default: ',',
  53. },
  54. isAnimated: {
  55. type: Boolean,
  56. default: false,
  57. },
  58. transition: {
  59. type: Boolean,
  60. default: false,
  61. },
  62. isCapital: {
  63. type: Boolean,
  64. default: false,
  65. },
  66. duration: {
  67. type: Number,
  68. default: 1000,
  69. },
  70. },
  71. data() {
  72. return {
  73. formatValue: 0,
  74. isMounted: false,
  75. }
  76. },
  77. watch: {
  78. value: {
  79. handler(val, oldVal) {
  80. /* istanbul ignore if */
  81. if (!inBrowser && !this.isMounted) {
  82. this.formatValue = val
  83. return
  84. }
  85. if (this.isAnimated || this.transition) {
  86. this.$_doAnimateDisplay(oldVal, val)
  87. } else {
  88. this.formatValue = val
  89. }
  90. },
  91. immediate: true,
  92. },
  93. },
  94. computed: {
  95. legalPrecision() {
  96. return this.precision > 0 ? this.precision : 0
  97. },
  98. },
  99. mounted() {
  100. this.isMounted = true
  101. },
  102. methods: {
  103. // MARK: private methods
  104. $_doAnimateDisplay(fromValue = 0, toValue = 0) {
  105. /* istanbul ignore next */
  106. const step = percent => {
  107. if (percent === 1) {
  108. this.formatValue = toValue
  109. return
  110. }
  111. this.formatValue = fromValue + (toValue - fromValue) * percent
  112. }
  113. /* istanbul ignore next */
  114. const verify = id => id
  115. Animate.start(step, verify, noop, this.duration)
  116. },
  117. },
  118. }
  119. </script>
  120. <style lang="scss">
  121. .md-amount{
  122. &.numerical{
  123. font-family: font-family-number
  124. }
  125. }
  126. </style>