calc_util.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /**
  2. * Created by Tony on 2017/6/21.
  3. * Modified by CSL, 2017-08-01
  4. * 引入多套计算程序、费率同步、人工系数同步、改进基数计算、费字段映射等。
  5. */
  6. let executeObj = {
  7. treeNode: null,
  8. at: function(ID) {
  9. let me = executeObj,
  10. rst = 0;
  11. rst = me.treeNode.data.calcTemplate.compiledTemplate[ID].unitFee;
  12. rst = parseFloat(rst);
  13. return rst;
  14. },
  15. base: function(calcBaseName) {
  16. let me = executeObj, rst = 0,
  17. base = getRationCalcBase(calcBaseName);
  18. if (base != null) {
  19. let price = 0, tmpSum = 0;
  20. for (let glj of me.treeNode.data.gljList) {
  21. if (base.gljTypes.indexOf(glj.type) >= 0) {
  22. if (base.calcType == baseCalc){ price = glj["basePrice"];}
  23. else if (base.calcType == adjustCalc){price = glj["adjustPrice"];}
  24. else if (base.calcType == budgetCalc){price = glj["marketPrice"];}
  25. else if (base.calcType == diffCalc){price = glj["marketPrice"] - glj["adjustPrice"];};
  26. };
  27. tmpSum = tmpSum + glj["quantity"] * price;
  28. glj = null;
  29. };
  30. rst = tmpSum;
  31. };
  32. return rst;
  33. }
  34. /* factor: function(factorID) {
  35. let me = executeObj;
  36. let rst = 7.77;
  37. return rst;
  38. }*/
  39. };
  40. class Calculation {
  41. // 先编译公用的基础数据
  42. compilePublics(feeRates, labourCoes, feeTypes){
  43. let me = this;
  44. let private_compile_feeFile = function() {
  45. if (feeRates) {
  46. me.compiledFeeRates = {};
  47. for (let rate of feeRates) {
  48. me.compiledFeeRates["feeRate_" + rate.ID] = rate;
  49. }
  50. }
  51. };
  52. let private_compile_labourCoeFile = function() {
  53. if (labourCoes) {
  54. me.compiledLabourCoes = {};
  55. for (let coe of labourCoes) {
  56. me.compiledLabourCoes["LabourCoe_" + coe.ID] = coe;
  57. }
  58. }
  59. };
  60. let private_compile_feeType = function() {
  61. if (feeTypes) {
  62. me.compiledFeeTypes = {};
  63. for (let ft of feeTypes) {
  64. me.compiledFeeTypes[ft.type] = ft.name;
  65. }
  66. }
  67. };
  68. private_compile_feeFile();
  69. private_compile_labourCoeFile();
  70. private_compile_feeType();
  71. };
  72. compileTemplate(template){
  73. let me = this;
  74. template.hasCompiled = false;
  75. template.errs = [];
  76. let private_extract_ID = function(str, idx){
  77. let rst = '', lBracket = 0, rBracket = 0, firstIdx = idx, lastIdx = 0;
  78. for (let i = idx; i < str.length; i++) {
  79. if (str[i] === '(') {
  80. lBracket++;
  81. if (lBracket == 1) firstIdx = i + 1;
  82. }
  83. if (str[i] === ')') {
  84. rBracket++;
  85. if (lBracket == rBracket) {
  86. lastIdx = i - 1;
  87. if (lastIdx > firstIdx) {
  88. if (str[firstIdx] === "'") firstIdx++;
  89. if (str[lastIdx] !== "'") lastIdx++;
  90. if (lastIdx > firstIdx) {
  91. rst = str.slice(firstIdx, lastIdx);
  92. }
  93. }
  94. break;
  95. }
  96. }
  97. }
  98. return rst;
  99. };
  100. let private_parse_ref = function(item, itemIdx){
  101. let idx = item.expression.indexOf('@(', 0);
  102. while (idx >= 0) {
  103. let ID = private_extract_ID(item.expression, idx);
  104. if (ID.length > 0) {
  105. let subItem = template.compiledTemplate[ID];
  106. if (subItem) {
  107. if (subItem.ID !== item.ID) {
  108. private_parse_ref(subItem, template.compiledTemplate[ID + "_idx"]);
  109. } else {
  110. template.errs.push("There exists the self refer ID: " + ID);
  111. }
  112. } else {
  113. template.errs.push("There exists the invalid ID by which could not find the item: " + ID);
  114. console.log('invalid ID: ' + ID);
  115. }
  116. }
  117. idx = item.expression.indexOf('@(', idx + ID.length + 3);
  118. }
  119. if (template.compiledSeq.indexOf(itemIdx) < 0) {
  120. template.compiledSeq.push(itemIdx);
  121. }
  122. };
  123. let private_setup_seq = function(item, itemIdx){
  124. if (template.compiledSeq.indexOf(itemIdx) < 0) {
  125. private_parse_ref(item, itemIdx);
  126. }
  127. };
  128. let private_compile_items = function() {
  129. for (let idx of template.compiledSeq) {
  130. let item = template.calcItems[idx];
  131. item.compiledExpr = item.expression.split('@(').join('$CE.at(');
  132. item.compiledExpr = item.compiledExpr.split('base(').join('$CE.base(');
  133. if (item.labourCoeID){
  134. let lc = me.compiledLabourCoes["LabourCoe_" + item.labourCoeID].coe;
  135. item.dispExpr = item.dispExpr.replace(/L/gi, lc.toString());
  136. item.compiledExpr = item.compiledExpr.replace(/L/gi, lc.toString());
  137. };
  138. if (item.feeRateID) {
  139. item.feeRate = me.compiledFeeRates["feeRate_" + item.feeRateID].rate;
  140. };
  141. // 字段名映射
  142. item.displayFieldName = me.compiledFeeTypes[item.fieldName];
  143. }
  144. };
  145. if (template && template.calcItems && template.calcItems.length > 0) {
  146. template.compiledSeq = [];
  147. template.compiledTemplate = {};
  148. for (let i = 0; i < template.calcItems.length; i++) {
  149. let item = template.calcItems[i];
  150. template.compiledTemplate[item.ID] = item;
  151. template.compiledTemplate[item.ID + "_idx"] = i;
  152. }
  153. for (let i = 0; i < template.calcItems.length; i++) {
  154. private_setup_seq(template.calcItems[i], i);
  155. }
  156. if (template.errs.length == 0) {
  157. private_compile_items();
  158. template.hasCompiled = true;
  159. } else {
  160. console.log('errors: ' + template.errs.toString());
  161. }
  162. };
  163. };
  164. calculate($treeNode){
  165. let me = this;
  166. let template = $treeNode.data.calcTemplate;
  167. if ($treeNode && template.hasCompiled) {
  168. let $CE = executeObj;
  169. $CE.treeNode = $treeNode;
  170. if (!$treeNode.fees) {
  171. $treeNode.fees = [];
  172. $treeNode.feesIndex = {};
  173. };
  174. for (let idx of template.compiledSeq) {
  175. let calcItem = template.calcItems[idx];
  176. let feeRate = calcItem.feeRate;
  177. if (!feeRate) feeRate = 100; // 100%
  178. calcItem.unitFee = eval(calcItem.compiledExpr) * feeRate * 0.01; // 如果eval()对清单树有影响,就换成小麦的Expression对象再试
  179. let quantity = $treeNode.data.quantity;
  180. if (!quantity) quantity = 0;
  181. calcItem.totalFee = calcItem.unitFee * quantity;
  182. // 费用同步到定额
  183. // 引入小麦的字段检测后,快速切换定额出现计算卡顿现象,过多的循环造成。这里把她的代码拆出来,减少微循环。
  184. if (!$treeNode.feesIndex[calcItem.fieldName]){
  185. let fee = {
  186. 'fieldName': calcItem.fieldName,
  187. 'unitFee': calcItem.unitFee,
  188. 'totalFee': calcItem.totalFee,
  189. 'tenderUnitFee': 0,
  190. 'tenderTotalFee': 0
  191. };
  192. $treeNode.fees.push(fee);
  193. $treeNode.feesIndex[calcItem.fieldName] = fee;
  194. }
  195. else{
  196. $treeNode.feesIndex[calcItem.fieldName].unitFee = calcItem.unitFee;
  197. $treeNode.feesIndex[calcItem.fieldName].totalFee = calcItem.totalFee;
  198. }
  199. }
  200. }
  201. }
  202. }