如何拆分【财务会计金额】控制回显?

518 阅读4分钟

项目场景:

对发票、单据等进行模拟,可以进行实时的输入、计算、回填

问题描述:

需求一个工具函数可以实现
单据的金额部分需要进行分割显示,并且当金额不足X位的时候,在金额前方补上'¥'

不需要补足符号的情况 不需要补符号的情况 需要补足符号的情况需要补符号的情况


原因分析:

我们对需要填写金额的部分的第一个格子进行包裹,当用户点击金额区域的时候,监听点击事件触发相对定位的input框出现。输入框onBlur的时候调用工具函数,解析用户输入的内容,按照需求进行分割回填和是否添上符号。

解决方案:

首先我们只判断用户输入的内容均为合法数字的情况(正整数或至多两位小数)。 那么我们首先需要判断的就是,对传入的输入框结果进行处理,整数补足两位小数,超出两位小数的进行强制保留为两位。 假设用户现在输入9527,我们期望的值应该是9527.00,所以这里使用了toFixed()方法。

number.toFixed(x) 可把 Number 四舍五入为指定小数位数的数字。

通过这个方法,我们成功的将值处理为了我们期望的格式。接下来我们需要对他的整数和小数部分进行拆解,方便我们进行逐个回填和排列。而整数和小数部分最明显的标志就是小数点,我们以小数点为分界,使用split()方法

string.split(separator,limit) 用于把一个字符串分割成字符串数组。

const price = "9527"
const cacheArr = Number(price).toFixed(2).split("."); // ["9527","00"]
这样 cacheArr就是一个由整数部分和小数部分组成的数组了。既然整数和小数已经拆解完毕,我们就需要逐位的进行拆解。
const price = "9527"
const cacheArr = Number(price).toFixed(2).replace(/,/g, "").split("."); // ["9527","00"]
const integer = cacheArr[0].split('');  // ["9","5","2","7"]
const decimal = cacheArr[1].split('');  // ["0","0"]
这里的思路是我们此处得到的小数永远是恒定的两位,所以小数部分不需要过多考虑。问题在于整数部分如何按照他们自己的数位回填,可能大家第一个反应是将整数部分依次进行除法运算,例如先➗1000得到千位,➗100得到百位。这也算是一个解决办法,但是这样过于冗长也进行了多次计算浪费性能。还需要多个变量来存储对应的数位进行回填。 我们调换一个思路,为了符合回填和添加符号的逻辑,数组的第0位应该是个位,第1位是十位,以此类推。通过观察发现如果将整数数组倒置,正好符合刚刚的这个想法。所以这里可以使用reverse()方法将整数数组倒置我们可以得到

array.reverse()方法用于颠倒数组中元素的顺序。

const integer = cacheArr[0].split('').reverse();  // ["7","2","5","9"]
此时我们的整数和小数部分已经格式化好了,直接在单据中按照位数进行回填即可~
但是需求中还提到,当金额不足X位的时候,在金额前方补上'¥'。既然我们已经可以自如的拆解数组了,那加符号还不是易如反掌~(*拿来吧你!*)
我们这里多设置一个形参,用来存储显示的最大整数位数。
假设我们的需求为金额不足100W时,在金额前方添加'¥'。100W是7位整数,所以我们设置形参为7
const idigits = 7;
if (integer.length > digits) {
	return { integer: ["误", "有", "入", "输"], decimal: [] }
} else {
	integer.push('¥')  // ["7","2","5","9","¥"]
}
至此为止,我们的需求基本上都已经满足了,接下来要做的就是对我们的函数进行抽离和容错处理。
首先,我们需要分析我们的函数中需要几个形参。
上文中我们提到的形参有两个 ,"金额"、"最大整数位数"。为了适应多个场景,某些场景下可能不需要对符号进行补充,所以我这里还增加了一个可选参数,"是否需要补足符号"。
确定了函数的形参个数,我们就只需要将已经写好的代码放进去,再进行相应的容错处理即可。

下面就是完整的代码块~~
    /**
   * 金额拆解拼接
   * @param price string 需要处理的金额
   * @param digits number 处理金额整数的位数,如果输入超出位数会返回输入有误
   * @param noSymbol boolean 可选参数,为true时不满上限位数不会加上货币符号
   * @param return { integer: [], decimal: [] }
   */
    function dismantlingPrice(price: string, digits: number, noSymbol?: boolean) {
      if (price == '') return { integer: [], decimal: [] }
      if (/^\d+(\.\d+)?$/.test(price)) {
        const cacheArr = Number(price).toFixed(2).split(".");
        const integer = cacheArr[0].split('').reverse();
        const decimal = cacheArr[1].split('');
        if (integer.length > digits) {
          return { integer: ["误", "有", "入", "输"], decimal: [] }
        }
        if (integer.length < digits && !noSymbol) {
          integer.push('¥')
        }
        return { integer: integer, decimal: decimal }
      }
      return { integer: ["误", "有", "入", "输"], decimal: [] }
    }

以上就是本次思考的全部过程啦······如果文章中有错误或者可以优化的地方,欢迎大佬指教~

在这里插入图片描述