/** * productContent 工具类 * 用于处理合同产品内容的各种操作 */ // 默认产品内容结构 const DEFAULT_PRODUCT_CONTENT = { products: [], productName: '', remark: '', totalQuantity: 0, totalTaxTotal: 0, totalAmountInWords: '零元整' }; /** * 解析 productContent JSON 字符串 * @param {string} jsonStr - JSON 字符串 * @returns {Object} 解析后的对象 */ export function parseProductContent(jsonStr) { if (!jsonStr) { return { ...DEFAULT_PRODUCT_CONTENT }; } try { const data = JSON.parse(jsonStr); return { ...DEFAULT_PRODUCT_CONTENT, ...data, products: data.products || [] }; } catch (error) { console.error('解析 productContent 失败:', error); return { ...DEFAULT_PRODUCT_CONTENT }; } } /** * 将对象转换为 productContent JSON 字符串 * @param {Object} data - 产品内容对象 * @returns {string} JSON 字符串 */ export function stringifyProductContent(data) { const content = { ...DEFAULT_PRODUCT_CONTENT, ...data }; return JSON.stringify(content, null, 2); } /** * 计算产品列表的总数量 * @param {Array} products - 产品列表 * @returns {number} 总数量 */ export function calculateTotalQuantity(products) { if (!products || !Array.isArray(products)) { return 0; } return products.reduce((total, item) => { return total + (parseFloat(item.quantity) || 0); }, 0); } /** * 计算产品列表的含税总额 * @param {Array} products - 产品列表 * @returns {number} 含税总额 */ export function calculateTotalTaxTotal(products) { if (!products || !Array.isArray(products)) { return 0; } return products.reduce((total, item) => { return total + (parseFloat(item.taxTotal) || 0); }, 0); } /** * 计算单个产品的含税总额 * @param {Object} product - 产品对象 * @returns {number} 含税总额 */ export function calculateProductTaxTotal(product) { if (!product) return 0; const quantity = parseFloat(product.quantity) || 0; const taxPrice = parseFloat(product.taxPrice) || 0; return quantity * taxPrice; } /** * 重新计算所有产品的含税总额和总计 * @param {Object} content - 产品内容对象 * @returns {Object} 更新后的产品内容对象 */ export function recalculateTotals(content) { if (!content) { return { ...DEFAULT_PRODUCT_CONTENT }; } const products = (content.products || []).map(product => ({ ...product, taxTotal: calculateProductTaxTotal(product) })); const totalQuantity = calculateTotalQuantity(products); const totalTaxTotal = calculateTotalTaxTotal(products); return { ...content, products, totalQuantity, totalTaxTotal, totalAmountInWords: convertToChinese(totalTaxTotal) }; } /** * 将订单明细项转换为产品项 * @param {Object} orderItem - 订单明细对象 * @returns {Object} 产品项对象 */ export function convertOrderItemToProduct(orderItem) { if (!orderItem) return {}; return { spec: orderItem.finishedProductSpec || '', material: orderItem.material || '', quantity: parseFloat(orderItem.weight) || 0, taxPrice: parseFloat(orderItem.contractPrice) || 0, noTaxPrice: parseFloat(orderItem.itemAmount) || 0, taxTotal: (parseFloat(orderItem.contractPrice) || 0) * (parseFloat(orderItem.weight) || 0), remark: orderItem.remark || '' }; } /** * 将订单明细列表转换为产品内容对象 * @param {Array} orderItems - 订单明细列表 * @param {string} productName - 产品名称 * @param {string} remark - 备注 * @returns {Object} 产品内容对象 */ export function convertOrderItemsToContent(orderItems, productName = '', remark = '') { const products = (orderItems || []).map(convertOrderItemToProduct); const content = { products, productName, remark }; return recalculateTotals(content); } /** * 添加产品项到产品内容 * @param {Object} content - 产品内容对象 * @param {Object} product - 要添加的产品项 * @returns {Object} 更新后的产品内容对象 */ export function addProduct(content, product) { if (!content) content = { ...DEFAULT_PRODUCT_CONTENT }; if (!product) return content; const newContent = { ...content, products: [...(content.products || []), { ...product }] }; return recalculateTotals(newContent); } /** * 删除产品内容中的产品项 * @param {Object} content - 产品内容对象 * @param {number} index - 要删除的索引 * @returns {Object} 更新后的产品内容对象 */ export function removeProduct(content, index) { if (!content || !content.products || index < 0 || index >= content.products.length) { return content; } const newProducts = [...content.products]; newProducts.splice(index, 1); const newContent = { ...content, products: newProducts }; return recalculateTotals(newContent); } /** * 更新产品内容中的产品项 * @param {Object} content - 产品内容对象 * @param {number} index - 要更新的索引 * @param {Object} product - 新的产品项数据 * @returns {Object} 更新后的产品内容对象 */ export function updateProduct(content, index, product) { if (!content || !content.products || index < 0 || index >= content.products.length || !product) { return content; } const newProducts = [...content.products]; newProducts[index] = { ...newProducts[index], ...product }; const newContent = { ...content, products: newProducts }; return recalculateTotals(newContent); } /** * 数字金额转中文大写 * @param {number} amount - 数字金额 * @returns {string} 中文大写金额 */ export function convertToChinese(amount) { if (amount === 0) return '零元整'; const digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']; const units = ['', '拾', '佰', '仟']; const bigUnits = ['', '万', '亿']; let integerPart = Math.floor(amount); let decimalPart = Math.round((amount - integerPart) * 100); let result = ''; // 处理整数部分 if (integerPart > 0) { let unitIndex = 0; let bigUnitIndex = 0; while (integerPart > 0) { let section = integerPart % 10000; if (section > 0) { let sectionResult = ''; let temp = section; let unitIndexInSection = 0; while (temp > 0) { let digit = temp % 10; if (digit > 0) { sectionResult = digits[digit] + units[unitIndexInSection] + sectionResult; } else { // 避免连续的零 if (sectionResult && !sectionResult.startsWith('零')) { sectionResult = '零' + sectionResult; } } temp = Math.floor(temp / 10); unitIndexInSection++; } result = sectionResult + bigUnits[bigUnitIndex] + result; } integerPart = Math.floor(integerPart / 10000); bigUnitIndex++; } result += '元'; } // 处理小数部分 if (decimalPart === 0) { result += '整'; } else { const jiao = Math.floor(decimalPart / 10); const fen = decimalPart % 10; if (jiao > 0) { result += digits[jiao] + '角'; } if (fen > 0) { result += digits[fen] + '分'; } } return result; } /** * 获取默认产品内容对象 * @returns {Object} 默认产品内容 */ export function getDefaultProductContent() { return { ...DEFAULT_PRODUCT_CONTENT }; } /** * ProductContent 工具类 */ export default { parse: parseProductContent, stringify: stringifyProductContent, calculateTotalQuantity, calculateTotalTaxTotal, calculateProductTaxTotal, recalculateTotals, convertOrderItemToProduct, convertOrderItemsToContent, addProduct, removeProduct, updateProduct, convertToChinese, getDefault: getDefaultProductContent };