import Big from 'big.js'; /** * 数字金额转中文大写(支持整数、小数) * @param num - 待转换的金额(支持数字或字符串格式) * @returns 中文大写金额字符串 */ export function convertToChineseCapital(num: number | string): string { // 中文数字映射 const digits: readonly string[] = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']; // 基本单位(个、拾、佰、仟) const units: readonly string[] = ['', '拾', '佰', '仟']; // 大单位(万、亿、万亿) const bigUnits: readonly string[] = ['', '万', '亿', '万亿']; // 1. 标准化输入:保留4位小数,分割整数与小数部分 const [intPartRaw, decPartRaw] = Number(num).toFixed(4).split('.'); // 去除整数前导零,若全零则保留一个 '0' const intPart: string = intPartRaw.replace(/^0+/, '') || '0'; let result: string = ''; // 2. 处理整数部分 if (intPart === '0') { result = '零元'; } else { // 从右向左,每4位分为一组(处理万、亿等大单位) const groups: string[] = []; let tempInt: string = intPart; while (tempInt.length > 0) { groups.unshift(tempInt.slice(-4)); tempInt = tempInt.slice(0, -4); } // 遍历每一组进行转换 groups.forEach((group: string, gIndex: number) => { let groupStr: string = ''; let needZero: boolean = false; // 标记是否需要补零 for (let i = 0; i < group.length; i++) { const digit: number = parseInt(group[i], 10); const unitPos: number = group.length - 1 - i; // 当前数字对应的单位位置 if (digit === 0) { needZero = true; } else { // 补零(如果前面有0) if (needZero) { groupStr += '零'; needZero = false; } groupStr += digits[digit] + units[unitPos]; } } // 拼接大单位(万、亿) if (groupStr) { result += groupStr + bigUnits[groups.length - 1 - gIndex]; } }); result += '元'; } // 3. 处理小数部分(仅保留角、分,忽略毫、厘) const jiao: number = parseInt(decPartRaw[0], 10); // 角(第1位小数) const fen: number = parseInt(decPartRaw[1], 10); // 分(第2位小数) if (jiao === 0 && fen === 0) { result += '整'; } else { // 处理“角” if (jiao > 0) { result += digits[jiao] + '角'; } else if (jiao === 0 && fen > 0) { result += '零'; } // 处理“分” if (fen > 0) { result += digits[fen] + '分'; } } return result; } /** * 金额加法 * @param a 数值 * @param b 数值 * @returns 保留2位小数字符串 */ export function moneyAdd(a: number | string = 0, b: number | string = 0): string { return new Big(a).plus(b).toFixed(2); } // 金额减法 export function sub(a, b) { let r1, r2; try { r1 = a.toString().split('.')[1].length; } catch (e) { r1 = 0; } try { r2 = b.toString().split('.')[1].length; } catch (e) { r2 = 0; } const m = Math.pow(10, Math.max(r1, r2)); return (a * m - b * m) / m; } // 金额乘法 export function mul(a, b) { let m = 0; const s1 = a.toString(), s2 = b.toString(); try { m += s1.split('.')[1].length; } catch (e) {} try { m += s2.split('.')[1].length; } catch (e) {} return (Number(s1.replace('.', '')) * Number(s2.replace('.', ''))) / Math.pow(10, m); } // 金额除法 export function div(a, b) { let t1 = 0, t2 = 0; try { t1 = a.toString().split('.')[1].length; } catch (e) {} try { t2 = b.toString().split('.')[1].length; } catch (e) {} const x = Number(a.toString().replace('.', '')); const y = Number(b.toString().replace('.', '')); return (x / y) * Math.pow(10, t2 - t1); } // 保留2位小数(金额专用) export function toFixed2(val) { return Number(val).toFixed(2); } /** * 智能金额格式化(带单位:元/万元/亿元) * 兼容:数字、字符串、null、undefined * @param {number|string} amount 金额 * @returns {string} 格式化后带单位的金额 */ export function formatMoneyWithUnit(amount) { // 空值处理 if (amount == null || amount === '') return '0.00 元'; const num = Number(amount); if (isNaN(num)) return '0.00 元'; // 绝对值判断单位 const absNum = Math.abs(num); if (absNum >= 100000000) { // 亿元 return (num / 100000000).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',') + ' 亿元'; } else if (absNum >= 10000) { // 万元 return (num / 10000).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',') + ' 万元'; } else { // 元 return num.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',') + ' 元'; } } // 带货币符号(¥)版本 export function formatMoneyWithSymbol(amount) { return '¥' + formatMoneyWithUnit(amount); }