/** * Created by Tony on 2017/6/21. * Modified by CSL, 2017-08-01 * 引入多套计算程序、费率同步、人工系数同步、改进基数计算、费字段映射等。 */ let executeObj = { treeNode: null, template: null, calcBase: null, at: function(ID) { let me = executeObj, rst = 0; rst = me.template.compiledCalcItems[ID].unitFee; rst = parseFloat(rst); return rst; }, base: function(calcBaseName) { let me = executeObj, rst = 0, //base = getRationCalcBase(calcBaseName); base = me.calcBase[calcBaseName]; if (base != null) { let price = 0, tmpSum = 0; for (let glj of me.treeNode.data.gljList) { if (base.gljTypes.indexOf(glj.type) >= 0) { if (base.calcType == baseCalc){ price = glj["basePrice"];} else if (base.calcType == adjustCalc){price = glj["adjustPrice"];} else if (base.calcType == budgetCalc){price = glj["marketPrice"];} else if (base.calcType == diffCalc){price = glj["marketPrice"] - glj["adjustPrice"];}; }; tmpSum = tmpSum + glj["quantity"] * price; glj = null; }; rst = tmpSum; }; return rst; } }; class Calculation { // 先编译公用的基础数据 compilePublics(feeRates, labourCoes, feeTypes, calcBases){ let me = this; let private_compile_feeRateFile = function() { if (feeRates) { me.compiledFeeRates = {}; for (let rate of feeRates) { me.compiledFeeRates["feeRate_" + rate.ID] = rate; } } }; let private_compile_labourCoeFile = function() { if (labourCoes) { me.compiledLabourCoes = {}; for (let coe of labourCoes) { me.compiledLabourCoes["LabourCoe_" + coe.ID] = coe; } } }; let private_compile_feeType = function() { if (feeTypes) { me.compiledFeeTypes = {}; for (let ft of feeTypes) { me.compiledFeeTypes[ft.type] = ft.name; me.compiledFeeTypes[ft.name] = ft.type; // 中文预编译,可靠性有待验证 } } }; let private_compile_calcBase = function() { if (calcBases) { me.compiledCalcBases = {}; for (let cb of calcBases) { me.compiledCalcBases[cb.dispName] = cb; // 中文预编译,可靠性有待验证 } } }; private_compile_feeRateFile(); private_compile_labourCoeFile(); private_compile_feeType(); private_compile_calcBase(); me.compiledTemplates = {}; }; compileTemplate(template){ let me = this; me.compiledTemplates[template.ID] = template; template.hasCompiled = false; template.errs = []; let private_extract_ID = function(str, idx){ let rst = '', lBracket = 0, rBracket = 0, firstIdx = idx, lastIdx = 0; for (let i = idx; i < str.length; i++) { if (str[i] === '(') { lBracket++; if (lBracket == 1) firstIdx = i + 1; } if (str[i] === ')') { rBracket++; if (lBracket == rBracket) { lastIdx = i - 1; if (lastIdx > firstIdx) { if (str[firstIdx] === "'") firstIdx++; if (str[lastIdx] !== "'") lastIdx++; if (lastIdx > firstIdx) { rst = str.slice(firstIdx, lastIdx); } } break; } } } return rst; }; let private_parse_ref = function(item, itemIdx){ let idx = item.expression.indexOf('@(', 0); while (idx >= 0) { let ID = private_extract_ID(item.expression, idx); if (ID.length > 0) { let subItem = template.compiledCalcItems[ID]; if (subItem) { if (subItem.ID !== item.ID) { private_parse_ref(subItem, template.compiledCalcItems[ID + "_idx"]); } else { template.errs.push("There exists the self refer ID: " + ID); } } else { template.errs.push("There exists the invalid ID by which could not find the item: " + ID); console.log('invalid ID: ' + ID); } } idx = item.expression.indexOf('@(', idx + ID.length + 3); } if (template.compiledSeq.indexOf(itemIdx) < 0) { template.compiledSeq.push(itemIdx); } }; let private_setup_seq = function(item, itemIdx){ if (template.compiledSeq.indexOf(itemIdx) < 0) { private_parse_ref(item, itemIdx); } }; let private_compile_items = function() { for (let idx of template.compiledSeq) { let item = template.calcItems[idx]; item.compiledExpr = item.expression.split('@(').join('$CE.at('); item.compiledExpr = item.compiledExpr.split('base(').join('$CE.base('); if (item.labourCoeID){ let lc = me.compiledLabourCoes["LabourCoe_" + item.labourCoeID].coe; item.dispExpr = item.dispExpr.replace(/L/gi, lc.toString()); item.compiledExpr = item.compiledExpr.replace(/L/gi, lc.toString()); }; if (item.feeRateID) { item.feeRate = me.compiledFeeRates["feeRate_" + item.feeRateID].rate; }; // 字段名映射 item.displayFieldName = me.compiledFeeTypes[item.fieldName]; } }; if (template && template.calcItems && template.calcItems.length > 0) { template.compiledSeq = []; template.compiledCalcItems = {}; for (let i = 0; i < template.calcItems.length; i++) { let item = template.calcItems[i]; template.compiledCalcItems[item.ID] = item; template.compiledCalcItems[item.ID + "_idx"] = i; } for (let i = 0; i < template.calcItems.length; i++) { private_setup_seq(template.calcItems[i], i); } if (template.errs.length == 0) { private_compile_items(); template.hasCompiled = true; } else { console.log('errors: ' + template.errs.toString()); } }; }; calculate($treeNode){ let me = this; let templateID = $treeNode.data.calcTemplateID; if (!templateID) templateID = 1; let template = me.compiledTemplates[templateID]; $treeNode.data.calcTemplate = template; if ($treeNode && template.hasCompiled) { let $CE = executeObj; $CE.treeNode = $treeNode; $CE.template = template; $CE.calcBase = me.compiledCalcBases; if (!$treeNode.fees) { $treeNode.fees = []; $treeNode.feesIndex = {}; }; for (let idx of template.compiledSeq) { let calcItem = template.calcItems[idx]; let feeRate = calcItem.feeRate; if (!feeRate) feeRate = 100; // 100% calcItem.unitFee = eval(calcItem.compiledExpr) * feeRate * 0.01; // 如果eval()对清单树有影响,就换成小麦的Expression对象再试 let quantity = $treeNode.data.quantity; if (!quantity) quantity = 0; calcItem.totalFee = calcItem.unitFee * quantity; // 费用同步到定额 // 引入小麦的字段检测后,快速切换定额出现计算卡顿现象,过多的循环造成。这里把她的代码拆出来,减少微循环。 if (!$treeNode.feesIndex[calcItem.fieldName]){ let fee = { 'fieldName': calcItem.fieldName, 'unitFee': calcItem.unitFee, 'totalFee': calcItem.totalFee, 'tenderUnitFee': 0, 'tenderTotalFee': 0 }; $treeNode.fees.push(fee); $treeNode.feesIndex[calcItem.fieldName] = fee; } else{ $treeNode.feesIndex[calcItem.fieldName].unitFee = calcItem.unitFee; $treeNode.feesIndex[calcItem.fieldName].totalFee = calcItem.totalFee; } } } } }