在vue项目中千分位展示输入金额,获取金额千分位,金额大写的方法

实现效果:

  • 在用户输入完成input失焦的时候,input文本框中显示的是千分位格式的金额;在用户再次聚焦的input文本框时,文本框中展示的是正常的金额值,用户可以修改金额,失焦的时候再次千分位展示。

思路:

  • 用两个变量,一个变量负责展示,一个变量存储实际的值,保证在任何情况下,实际值不受影响,展示按需求去展示

main.js中引入公共方法

import validate from '@/utils/validate';
Vue.prototype.$validate = validate
Vue.use(validate)

validate.js方法

export default {
	//金额转换为千分位
  formatCurrency(value, str) {
    if (!str) str = '';
    // str 规定货币类型
    if (value == "0") return '0.00';
    if(value == ".") return '';
    if (!value) return '';
    let val = Number(value).toFixed(2) // 提前保留两位小数
    let intPart = parseInt(val) // 获取整数部分
    let intPartFormat = intPart.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') // 将整数部分逢三一断 ???
    let floatPart = '.00' // 预定义小数部分
    val = val.toString() // 将number类型转为字符串类型,方便操作
    let value2Array = val.split('.')
    if (value2Array.length === 2) { // =2表示数据有小数位
      floatPart = value2Array[1].toString() // 拿到小数部分
      if (floatPart.length === 1) { // 补0,实际上用不着
        return str + intPartFormat + '.' + floatPart + '0'
      } else {
        return str + intPartFormat + '.' + floatPart
      }
    } else {
      return str + intPartFormat + floatPart
    }
  },
//限制输入金额
  inputLimitAmount(val,digit){
    digit = digit || 12;
    let res = "";
    if(!val) return "";
    if(val == ".") return "";
    let matchArr = val.match(/\./g);
    if(matchArr && matchArr.length>1){
      res = null;
    }else{
      if(val.split('.')[0].length > digit){
        res = null;
      }else{
        res = val.split('.')[1] && val.split('.')[1].length > 2 ? val.split('.')[0] + '.' +  val.split('.')[1].slice(0,2) : val;
      }
    }
    return res ? res.replace(/[^0-9.]/g,"") : res;
  },
  // ======== 限制金额的输入及千分位展示 start============
  formatAmountFocus(_attr, dataForm){
    let that = _attr+'F';
    dataForm[that] = dataForm[_attr];
  },
  formatAmountInput(_attr, dataForm, digit){
    let that = _attr+'F';
    let $thisVal = dataForm[_attr];
    let $thatVal = dataForm[that];
    let dig = digit ? digit : 12;
    let formateVal = this.inputLimitAmount($thatVal,dig);
    if(formateVal == null){
      dataForm[that] = $thisVal
    }else{
      dataForm[that] = formateVal;
      dataForm[_attr] = formateVal ? Number(formateVal).toFixed(2) : formateVal;
    }
  },
  formatAmountBlur(_attr, dataForm){
    let that = _attr+'F';
    dataForm[that] = this.formatCurrency(dataForm[that]);
  },
  //  ======== 限制金额的输入及千分位展示 end======== 
  //获取金额大写的方法
	getMoneyHanzi(n) {
	  if ((!n && n==="") || (!n && n!=0)) return;
	  let str = 0
	  n = typeof n === 'number' ? n + '' : n
	  str = n.substring(n.indexOf('.') + 1, n.indexOf('.') + 3)
	  let fraction = ['角', '分']
	  let digit = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
	  let unit = [['元', '万', '亿'], ['', '拾', '佰', '仟']]
	  let s = ''
	  for (let i = 0; i < fraction.length; i++) {
	    if (i === 0) {
	      s += (digit[parseInt(n * 10 * Math.pow(10, i) % 10)] + fraction[i]).replace(/零./, '')
	    } else if (i === 1) {
	      if (str.length === 2) {
	        if (str.substring(0, 1) === '0') {
	          s = '零角'
	        }
	        if (str.substring(0, 2) === '00') {
	          s = '整'
	        }
	      }
	      s += (digit[(n * 10 * Math.pow(10, i) % 10).toFixed(0)] + fraction[i]).replace(/零./, '')
	    }
	  }
	  s = s || '整'
	  n = Math.floor(n);
	  //区分小数点左边是否有值(解决分位显示零几分缺陷)
	  let flag = n; 
	  for (let i = 0; i < unit[0].length && n > 0; i++) {
	    let p = ''
	    for (let j = 0; j < unit[1].length && n > 0; j++) {
	      p = digit[n % 10] + unit[1][j] + p
	      n = Math.floor(n / 10)
	    }
	    s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s
	  }
	  let sum = flag == 0?s.replace(/(零.)*零元/, '元').replace(/(零.)+/g, '').replace(/^整$/, '零元整'):s.replace(/(零.)*零元/, '元').replace(/(零.)+/g, '零').replace(/^整$/, '零元整')
	  return sum
	}

}

组件中引用

 <el-form-item label="单笔限额(元)">
   <el-input 
    	v-model="form.tranLmtF" 		
    	@focus="focus_Amount('tranLmt',$event)"
      	@input="inpLimit_Amount('tranLmt')" 	
      	@blur="getFormate_Amount('tranLmt')">
    </el-input>
 </el-form-item>

focus_Amount(filedName,ele) {
  this.$validate.formatAmountFocus(filedName, this.form);
  //下面这段代码是为了解决在IE11上为input赋值后,光标聚焦到最左侧的问题
  let obj = ele.srcElement;
  if(obj.setSelectionRange){
    obj.setSelectionRange(obj.value.length,obj.value.length);
  }else{
    var range = obj.createTextRange();
    range.collapse(true);
    range.moveStart("character",obj.value.length);
    range.moveEnd("character",0);
    range.select();
  }
},
inpLimit_Amount(filedName) {
  this.$validate.formatAmountInput(filedName, this.form);
},
// blur
getFormate_Amount(filedName) {
  this.$validate.formatAmountBlur(filedName, this.form);
  if( this.form[filedName] == "" ){
    this.form[filedName] = "0";
    this.form[filedName + 'F'] = "0.00";
  }
},
您希望在现有代码的基础上进一步扩展功能,使得价格能够同时展示为**大写形式**(例如“壹佰贰拾叁元肆角伍分”)。这是一个常见的需求,尤其是在财务系统或正式文档生成场景下。 下面是更新后的完整解决方案以及相关说明: --- ### 更新后的代码 ```vue <script lang="ts" setup> import { computed, ref } from 'vue'; import formatCurrencyToCapital from './utils/capitalFormat'; // 假设封装了一个工具函数用于转换成大写金额 // 定义组件选项 defineOptions({ name: 'ThousandSeparatorWithCapital' }); // 接收外部属性 const props = defineProps<{ price: number; // 输入的价格值(原始数据) }>(); // 小格式化价格 (千分位) const formattedPriceLowercase = computed(() => { const fixedPrice = parseFloat(props.price.toFixed(2)); return fixedPrice.toLocaleString('zh-CN', { minimumFractionDigits: 2 }); }); // 大写格式化价格 const formattedPriceUppercase = computed(() => { return formatCurrencyToCapital(props.price); }); </script> <template> <div class="price-container"> <!-- 显示小价格 --> <div class="lowercase-price">小:¥{{ formattedPriceLowercase }}</div> <!-- 显示大写价格 --> <div class="uppercase-price">大写:{{ formattedPriceUppercase }}</div> </div> </template> <style scoped> .lowercase-price { font-size: 16px; color: #ff5722; /* 橙红色 */ margin-bottom: 8px; } .uppercase-price { font-size: 14px; color: #333; /* 深灰色 */ } </style> ``` --- ### 新增的关键点解析 1. **引入辅助函数 `formatCurrencyToCapital`** - 此处假设有一个独立文件存放逻辑来完成数字转汉字的功能。如果您尚未拥有类似模块的话,可以参考下面提供的简单实现版本。 ```typescript // utils/capitalFormat.ts function formatCurrencyToCapital(amount) { if (!amount && amount !== 0){ return ''; } let cnNums = ['零','壹','贰','叁','肆','伍','陆','柒','捌','玖']; let cnIntRadice = ['', '拾', '佰', '仟']; // 整数部分的权次单位 let cnIntUnits = ['', '万', '亿', '兆']; // 更大的整数单元 let cnDecUnits = ['角', '分']; // 小数部分表示法 // 分离整数与分数部分 var integerPart = Math.floor(amount).toString(); var decimalPart = ((amount - Math.floor(amount)) * 100).toFixed(0).padStart(2,'0'); let resultArr = []; for(let i=integerPart.length;i>0;i-=4){ let chunk = parseInt(integerPart.slice(Math.max(i-4,0),i)) .toString().split('').reverse(); // 四个一组切割并反转方便匹配 let tmpStr=''; for(var j=chunk.length-1 ;j>=0;j--){ if(chunk[j]!=='0'){ tmpStr +=cnNums[parseInt(chunk[j])] + cnIntRadice[chunk.length-j-1]; } else{ if(tmpStr.indexOf("零")===-1 || !tmpStr.trim()){ tmpStr+="零"; } } } while(/零{2,}/g.test(tmpStr)){ tmpStr=tmpStr.replace(/零+/g,"零"); // 删除多余‘零’字串直到只剩一个为止. } if(cnIntUnits[Math.ceil((i)/4)-1]==='万'||cnIntUnits[Math.ceil((i)/4)-1]==='亿') tmpStr+=''+cnIntUnits[Math.ceil((i)/4)-1]; resultArr.unshift(tmpStr); } var decResult=""; for(const [index,digit] of [...decimalPart].entries()) decResult+=digit==='0'? "": `${cnNums[digit]}${cnDecUnits[index]}`; let finalResult=resultArr.join("").replace(/^零+/, "")+"圆"+decResult; return finalResult; } export default formatCurrencyToCapital ; ``` 2. **计算两个格式化的结果** - 我们分别通过 `computed` 属性得到普通的小价格表达式和对应的大写表述内容,并且将它们绑定到视图上渲染出来。 --- ### 示例效果 假定输入如下数值时的效果分别为: | Input Price | Output Lower Case | Output Upper Case | |-------------|-------------------------|-------------------------------------------| | 123456.78 | ¥123,456.78 | 壹拾贰万参仟肆佰伍拾陆园柒角捌分 | | 98765.43 | ¥98,765.43 | 玖万扒仟染百陆拾五园四角三分 | --- ### 注意事项 由于汉字书规则较为复杂,因此涉及到边界条件处理的地方较多,比如连续多个零只应读作一次等情况都需要充分测试验证无误后再部署上线使用.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值