最近有个需求是封装一个货币组件,翻了下网上+自己结合封装了一个简陋版的,包含可控制小数位,鼠标移入显示大写金额,格式化金额展示等功能。 项目是vue2 + ant Design Vue 1.7.8版本
- utils下新建一个numToCny.js文件夹;
- 数字转换,暴露方法
// 数字金额转大写
export const numToCny=(money)=>{
// 汉字的数字
var cnNums = new Array('零', '壹', '贰', '叁', '肆', '伍', '陆',
'柒', '捌', '玖');
// 基本单位
var cnIntRadice = new Array('', '拾', '佰', '仟');
// 对应整数部分扩展单位
var cnIntUnits = new Array('', '万', '亿', '兆');
// 对应小数部分单位
var cnDecUnits = new Array('角', '分', '毫', '厘');
// 整数金额时后面跟的字符
var cnInteger = '整';
// 整型完以后的单位
var cnIntLast = '元';
// 最大处理的数字
var maxNum = 999999999999999.9999;
// 金额整数部分
var integerNum;
// 金额小数部分
var decimalNum;
// 输出的中文金额字符串
var chineseStr = '';
// 分离金额后用的数组,预定义
var parts;
if (money == '') {
return '';
}
money = parseFloat(money);
if (money >= maxNum) {
// 超出最大处理数字
return '';
}
if (money == 0) {
chineseStr = cnNums[0] + cnIntLast + cnInteger;
return chineseStr;
}
// 转换为字符串
money = money.toString();
if (money.indexOf('.') == -1) {
integerNum = money;
decimalNum = '';
} else {
parts = money.split('.');
integerNum = parts[0];
decimalNum = parts[1].substr(0, 4);
}
// 获取整型部分转换
if (parseInt(integerNum, 10) > 0) {
var zeroCount = 0;
var IntLen = integerNum.length;
for (var i = 0; i < IntLen; i++) {
var n = integerNum.substr(i, 1);
var p = IntLen - i - 1;
var q = p / 4;
var m = p % 4;
if (n == '0') {
zeroCount++;
} else {
if (zeroCount > 0) {
chineseStr += cnNums[0];
}
// 归零
zeroCount = 0;
chineseStr += cnNums[parseInt(n)]
+ cnIntRadice[m];
}
if (m == 0 && zeroCount < 4) {
chineseStr += cnIntUnits[q];
}
}
chineseStr += cnIntLast;
}
// 小数部分
if (decimalNum != '') {
var decLen = decimalNum.length;
for (var i = 0; i < decLen; i++) {
var n = decimalNum.substr(i, 1);
if (n != '0') {
chineseStr += cnNums[Number(n)] + cnDecUnits[i];
}
}
}
if (chineseStr == '') {
chineseStr += cnNums[0] + cnIntLast + cnInteger;
} else if (decimalNum == '') {
chineseStr += cnInteger;
}
return chineseStr;
}
3.在组件中调用;
<!--
* @Description: 货币组件
-->
<template>
<div>
<a-tooltip :title="numToCny(this.value)" :get-popup-container="getPopupContainer">
<a-input
:value="formattedValue"
:prefix="record.options.prefix"
:suffix="record.options.suffix"
:placeholder="record.options.placeholder"
:disable="record.options.disable"
@input="handleInput"
/>
</a-tooltip>
</div>
</template>
<script>
import { numToCny } from '@/utils/numToCny';
export default {
props: {
record: {
type: Object,
},
value: {
type: [Number, String],
},
decimalNumber: {
type: Number,
}
},
computed: {
formattedValue() {
// 将值转换为字符串
let strValue = String(this.value);
// 正则表达式校验和替换
strValue = strValue.replace(/[^0-9.]/g, '');
// 根据小数点将值分割为整数部分和小数部分
const parts = strValue.split('.');
// 格式化整数部分,每三位添加逗号分隔符
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
// 重新组合整数部分和小数部分
strValue = parts.join('.');
return strValue;
},
},
methods: {
getPopupContainer(trigger) {
return trigger.parentElement;
},
handleInput(event) {
// 移除逗号分隔符
const inputValue = event.target.value.replace(/,/g, '');
// 使用正则表达式限制小数点后的最大输入长度
const regex = new RegExp(`^(\\d+\\.?\\d{0,${this.decimalNumber}})?$`);
const isValid = regex.test(inputValue);
if (isValid) {
this.$emit('change', inputValue);
} else {
// 如果输入不合法,将值重置为之前的值
this.$emit('change', this.value);
}
},
},
}
</script>
<style lang="scss" scoped>
</style>
4.父组件引用
<!-- 货币组件 -->
<CurrencyComponent
:record="record" // 我这里是将所有参数整合到了record里面
:value="record.options.defaultValue"
:decimalNumber="record.options.decimalNumber"
@change="(e) => { handleChange(e, record.model)}"
v-decorator="[
record.model, // input 的 name
{
initialValue: record.options.defaultValue, // 默认值
ruleCode: record.options.ruleCode,
rules: record.rules, // 验证规则
},]"
/>
// 下面是对于record参数的定义,可以根据自己需求拆分成单独的props
{
label: "货币组件",
type: "currency",
icon: "transaction",
options: {
width: "100%", // 宽度
defaultValue: '', // 默认值
prefix: '¥',
suffix: '人民币',
decimalNumber: 2, // 小数点位数
placeholder: "请输入金额",
disabled: false, // 是否禁用,false不禁用,true禁用
hidden: false,
colCountKey: 24, // 表单栅格
ifLineFeed: 'horizontal', // 组件布局
helpTips: '', // 帮助提示
labelWidth: 100, // 标签宽度
},
key: "",
rules: [{
required: false,
message: "必填项"
}]
},
5.使用效果