111 lines
2.8 KiB
TypeScript
111 lines
2.8 KiB
TypeScript
// utils/amountToChinese.js
|
|
export function amountToChinese(money) {
|
|
// 1. 参数处理
|
|
if (money === '' || money === null || money === undefined || isNaN(money)) {
|
|
return '';
|
|
}
|
|
|
|
// 2. 金额验证
|
|
if (Math.abs(money) > 9999999999999.99) {
|
|
throw new Error('金额超出范围 (最大: 9999999999999.99)');
|
|
}
|
|
|
|
// 3. 定义常量
|
|
const CN_NUMBERS = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
|
|
const CN_INTEGER_UNIT = ['', '拾', '佰', '仟'];
|
|
const CN_GROUP_UNIT = ['', '万', '亿', '兆'];
|
|
const CN_DECIMAL_UNIT = ['角', '分'];
|
|
const CN_FULL = '整';
|
|
const CN_NEGATIVE = '负';
|
|
const CN_YUAN = '元';
|
|
|
|
// 4. 处理符号
|
|
let isNegative = false;
|
|
if (money < 0) {
|
|
isNegative = true;
|
|
money = Math.abs(money);
|
|
}
|
|
|
|
// 5. 格式化为两位小数
|
|
let moneyStr = parseFloat(money).toFixed(2);
|
|
|
|
// 6. 分离整数和小数
|
|
const [integerPart, decimalPart] = moneyStr.split('.');
|
|
|
|
// 7. 转换整数部分
|
|
let chineseStr = '';
|
|
|
|
if (parseInt(integerPart, 10) > 0) {
|
|
// 按4位一组分割
|
|
const groups = [];
|
|
for (let i = integerPart.length; i > 0; i -= 4) {
|
|
groups.push(integerPart.substring(Math.max(0, i - 4), i));
|
|
}
|
|
|
|
// 处理每一组
|
|
for (let i = 0; i < groups.length; i++) {
|
|
let groupStr = '';
|
|
const group = groups[i].split('').reverse().join('');
|
|
let hasZero = false;
|
|
|
|
for (let j = 0; j < group.length; j++) {
|
|
const digit = parseInt(group[j], 10);
|
|
const unit = CN_INTEGER_UNIT[j];
|
|
|
|
if (digit === 0) {
|
|
if (!hasZero && j !== 0) {
|
|
groupStr = CN_NUMBERS[0] + groupStr;
|
|
hasZero = true;
|
|
}
|
|
} else {
|
|
groupStr = CN_NUMBERS[digit] + unit + groupStr;
|
|
hasZero = false;
|
|
}
|
|
}
|
|
|
|
// 去除尾部的零
|
|
groupStr = groupStr.replace(/零+$/, '');
|
|
|
|
// 添加组单位(万、亿、兆)
|
|
if (groupStr) {
|
|
groupStr += CN_GROUP_UNIT[i];
|
|
}
|
|
|
|
chineseStr = groupStr + chineseStr;
|
|
}
|
|
|
|
chineseStr += CN_YUAN;
|
|
}
|
|
|
|
// 8. 转换小数部分
|
|
if (decimalPart) {
|
|
const decInt = parseInt(decimalPart, 10);
|
|
if (decInt > 0) {
|
|
for (let i = 0; i < decimalPart.length; i++) {
|
|
const digit = parseInt(decimalPart[i], 10);
|
|
if (digit > 0) {
|
|
chineseStr += CN_NUMBERS[digit] + CN_DECIMAL_UNIT[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 9. 清理多余的零
|
|
chineseStr = chineseStr
|
|
.replace(/零+/g, '零')
|
|
.replace(/零([万亿兆])/g, '$1')
|
|
.replace(/零元/g, '元')
|
|
.replace(/元零?$/, '元');
|
|
|
|
// 10. 添加"整"或处理负数
|
|
if (!chineseStr.includes('角') && !chineseStr.includes('分')) {
|
|
chineseStr += CN_FULL;
|
|
}
|
|
|
|
if (isNegative) {
|
|
chineseStr = CN_NEGATIVE + chineseStr;
|
|
}
|
|
|
|
return chineseStr;
|
|
}
|