import { trimZeros, roundHalfUp } from "./formatNumber.js"; /** * 通用的表格合计方法 * @param {Object} param - 包含表格列配置和数据源的对象 * @param {Array} summaryProps - 需要汇总的字段名数组 * @param {Object} specialFormat - 特殊格式化规则:字段名 -> 格式化选项(如是否去掉小数) * 支持 { noDecimal: true } 取整显示 * { trimZeros: true, decimalPlaces: 6 } 最多保留 6 位小数并去掉末尾多余的 0 * { roundEach: 2 } 每行先按 2 位小数四舍五入再求和, * 用于金额列:保证合计与列内展示值相加完全一致 * { formatter: fn } 自定义格式化函数,优先级最高 * { decimalPlaces: 2 } 固定保留 2 位小数(默认) * @returns {Array} 合计行数据 */ const summarizeTable = (param, summaryProps, specialFormat = {}) => { const { columns, data } = param; const sums = []; columns.forEach((column, index) => { if (index === 0) { sums[index] = "合计"; return; } const prop = column.property; if (summaryProps.includes(prop)) { const rule = specialFormat[prop]; const values = data.map((item) => { const val = Number(item[prop]); // NaN 保持 NaN,便于下面判断「整列都不是数字」 if (Number.isNaN(val)) return NaN; return rule && rule.roundEach != null ? roundHalfUp(val, rule.roundEach) : val; }); // 只对有效数字进行求和 if (!values.every(isNaN)) { const sum = values.reduce( (acc, val) => (!isNaN(val) ? acc + val : acc), 0 ); if (specialFormat[prop] && specialFormat[prop].noDecimal) { // 如果指定了不需要保留小数,则直接转换为整数 sums[index] = Math.round(sum).toString(); } else if ( specialFormat[prop] && typeof specialFormat[prop].formatter === "function" ) { // 自定义格式化函数优先 sums[index] = specialFormat[prop].formatter(sum); } else if (specialFormat[prop] && specialFormat[prop].trimZeros) { // 指定了去掉末尾多余的 0(最多保留 decimalPlaces 位,默认 6 位) sums[index] = trimZeros(sum, specialFormat[prop].decimalPlaces ?? 6); } else { // 默认保留两位小数 sums[index] = parseFloat(sum).toFixed( specialFormat[prop]?.decimalPlaces ?? 2 ); } } else { sums[index] = ""; } } else { sums[index] = ""; } }); return sums; }; // 不含税总价计算,decimals 为保留小数位数(销售/采购相关页面传 6) const calculateTaxExclusiveTotalPrice = ( taxInclusiveTotalPrice, taxRate, decimals = 2 ) => { const taxRateDecimal = taxRate / 100; return (taxInclusiveTotalPrice / (1 + taxRateDecimal)).toFixed(decimals); }; // 含税总价计算,decimals 为保留小数位数(销售/采购相关页面传 6) const calculateTaxIncludeTotalPrice = ( taxInclusiveUnitPrice, quantity, decimals = 2 ) => { return (taxInclusiveUnitPrice * quantity).toFixed(decimals); }; // 导出函数供其他文件使用 export { summarizeTable, calculateTaxExclusiveTotalPrice, calculateTaxIncludeTotalPrice, };