calc_base.js 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540
  1. /**
  2. * Created by Zhong on 2017/11/28.
  3. */
  4. let cbTools = {
  5. isDef: function (v) {
  6. return v !== undefined && v !== null;
  7. },
  8. isUnDef: function (v) {
  9. return v === undefined || v === null;
  10. },
  11. isNum: function (v) {
  12. return this.isDef(v) && !isNaN(v) && v !== Infinity;
  13. },
  14. isFlag: function (v) {
  15. return this.isDef(v) && this.isDef(v.flagsIndex) && this.isDef(v.flagsIndex.fixed) && this.isDef(v.flagsIndex.fixed.flag);
  16. },
  17. returnV: function (v, r) {
  18. if (this.isDef(v)) {
  19. return v;
  20. }
  21. return r;
  22. },
  23. findBill: function (fixedFlag) {
  24. return this.isDef(calcBase.fixedBills[fixedFlag]) ? calcBase.fixedBills[fixedFlag]["bill"] : null;
  25. },
  26. findNodeByFlag: function (fixedFlag) {
  27. let bills = this.findBill(fixedFlag);
  28. if (!bills) {
  29. return null;
  30. }
  31. return this.getNodeByID(bills.ID);
  32. },
  33. /*//通过行获取根节点清单
  34. getBillByRow: function (items, row) {
  35. if(cbTools.isDef(items[row]) &&
  36. cbTools.isUnDef(items[row]['parent'])&&
  37. cbTools.isDef(items[row]['sourceType']) &&
  38. items[row]['sourceType'] === calcBase.project.Bills.getSourceType()){
  39. return items[row];
  40. }
  41. return null;
  42. },*/
  43. //通过行获取节点清单
  44. getBillByRow: function (items, row) {
  45. if (cbTools.isDef(items[row]) && cbTools.isDef(items[row]["sourceType"]) && items[row]["sourceType"] === calcBase.project.Bills.getSourceType()) {
  46. return items[row];
  47. }
  48. return null;
  49. },
  50. //通过ID获取节点行
  51. getRowByID: function (items, ID) {
  52. for (let i = 0, len = items.length; i < len; i++) {
  53. if (items[i]["data"]["ID"] == ID) {
  54. return i + 1;
  55. }
  56. }
  57. return null;
  58. },
  59. //通过ID获取节点
  60. getNodeByID: function (ID) {
  61. return this.isDef(calcBase.project.mainTree.nodes["id_" + ID]) ? calcBase.project.mainTree.nodes["id_" + ID] : null;
  62. },
  63. //获取该节点所有父节点
  64. getParents: function (node) {
  65. let rst = [];
  66. rst.push(node);
  67. rParent(node);
  68. return rst;
  69. function rParent(node) {
  70. if (cbTools.isDef(node.parent)) {
  71. rst.push(node.parent);
  72. rParent(node.parent);
  73. }
  74. }
  75. },
  76. //获取所有节点的ID
  77. getNodeIDs: function (nodes) {
  78. let rst = [];
  79. for (let i = 0, len = nodes.length; i < len; i++) {
  80. if (this.isDef(nodes[i]["data"]["ID"])) {
  81. rst.push(nodes[i]["data"]["ID"]);
  82. }
  83. }
  84. return rst;
  85. },
  86. //根据公式获取相关的节点
  87. getNodesByExp: function (node, formulaNodesArr) {
  88. let exp = node.data.calcBase;
  89. let rst = [],
  90. ids = [];
  91. if (this.isUnDef(exp) || exp === "") {
  92. return rst;
  93. }
  94. let findChildNodes = []; //直接引用的节点,这些节点可能存在子节点,子节点才有公式,因此获取这些节点的子公式节点
  95. //获取表达式中的基数和行引用
  96. let figureF = cbParser.getFigureF(cbParser.getFigure(exp), cbParser.getUID(cbParser.getFIDArr(exp)));
  97. //首先提取出多处引用的进行排序
  98. for (let i = 0, len = figureF.length; i < len; i++) {
  99. let figure = figureF[i];
  100. if (figure.type === "base" && calcBase.baseFigures && cbTools.isDef(calcBase.baseFigures[figure.value])) {
  101. let bill = this.isDef(calcBase.baseFigures[figure.value]["fixedBill"]) ? calcBase.baseFigures[figure.value]["fixedBill"]["bill"] : null;
  102. let figureMultiRef = calcBase.baseFigures[figure.value]["multiRef"];
  103. if (this.isDef(figureMultiRef)) {
  104. for (let flag of figureMultiRef) {
  105. let refNode = this.findBill(flag) ? this.getNodeByID(this.findBill(flag).ID) : null;
  106. if (refNode && !ids.includes(refNode.data.ID)) {
  107. findChildNodes.push(refNode);
  108. ids.push(refNode.data.ID);
  109. }
  110. }
  111. } else if (this.isDef(bill) && ids.indexOf(bill.ID) === -1) {
  112. let node = this.getNodeByID(bill.ID);
  113. if (this.isDef(node) && !ids.includes(node.data.ID)) {
  114. findChildNodes.push(node);
  115. ids.push(node.data.ID);
  116. }
  117. }
  118. } else if (figure.type === "id") {
  119. let node = this.getNodeByID(figure.value);
  120. if (this.isDef(node) && !ids.includes(node.data.ID)) {
  121. findChildNodes.push(node);
  122. ids.push(node.data.ID);
  123. }
  124. }
  125. }
  126. if (findChildNodes.length > 0) {
  127. let childrenNodes = calcTools.getChildrenFormulaNodes(node, formulaNodesArr, findChildNodes);
  128. rst = rst.concat(childrenNodes);
  129. }
  130. return rst;
  131. },
  132. //需要用到计算基数的时候,先找出所有的固定清单,避免每个基数都要去遍历寻找清单
  133. setFixedBills: function (project, billsObj, fixedFlag) {
  134. let bills = project.Bills.datas;
  135. for (let i = 0, len = bills.length; i < len; i++) {
  136. if (this.isDef(bills[i].flagsIndex.fixed)) {
  137. for (let flag in fixedFlag) {
  138. if (fixedFlag[flag] === bills[i].flagsIndex.fixed.flag) {
  139. billsObj[fixedFlag[flag]] = Object.create(null);
  140. billsObj[fixedFlag[flag]]["base"] = Object.create(null);
  141. billsObj[fixedFlag[flag]]["bill"] = bills[i];
  142. }
  143. }
  144. }
  145. }
  146. },
  147. //清单基数设置所属固定清单属性
  148. setBaseBills: function (baseFigure, fixedBills) {
  149. for (let i in baseFigure) {
  150. let calcBase = baseFigure[i];
  151. calcBase.fixedBill = null;
  152. if (cbTools.isDef(calcBase.fixedFlag) && cbTools.isDef(fixedBills[calcBase.fixedFlag])) {
  153. fixedBills[calcBase.fixedFlag]["base"][i] = calcBase;
  154. calcBase.fixedBill = fixedBills[calcBase.fixedFlag];
  155. }
  156. }
  157. },
  158. //设置清单固定行下可用的基数映射
  159. //@param {Object}baseFigures(当前项目可用总基数配置表) {Object}mapping(可用基数映射,初始为空object,目标:{flag: Array(baseList)}) eg: {'1': ['xx费']}
  160. setValidBaseMapping: function (baseFigures, mapping) {
  161. let baseFigures2 = {};
  162. if (typeof filterByProjectKind !== "undefined") {
  163. const engName = projectObj.project.property.engineeringName;
  164. for (let baseName in baseFigures) {
  165. const calcBase = baseFigures[baseName];
  166. if (calcBase.projectKind) {
  167. if (calcBase.projectKind.includes(engName)) baseFigures2[baseName] = calcBase;
  168. } else {
  169. baseFigures2[baseName] = calcBase;
  170. }
  171. }
  172. } else {
  173. baseFigures2 = baseFigures;
  174. }
  175. //清单固定行数组[1, 2...]
  176. let allFlags = [];
  177. //清单固定行与子清单固定行映射
  178. let subFlagMapping = {};
  179. for (let attr in fixedFlag) {
  180. let flag = fixedFlag[attr];
  181. allFlags.push(flag);
  182. let subFlagList = this.getSubFlagList(flag);
  183. subFlagMapping[flag] = subFlagList;
  184. }
  185. for (let baseName in baseFigures2) {
  186. let calcBase = baseFigures2[baseName],
  187. filter = calcBase.filter || Object.values(fixedFlag), // filter为空则全部部分都可用该基数
  188. pick = calcBase.pick; //挑选或过滤
  189. /* if (!filter) {
  190. continue;
  191. } */
  192. //pick为true,则filter中的清单固定行可使用此基数(及其子清单固定行),
  193. //pick为false除去filter中的清单固定行(及其子清单固定行),其他可使用此基数(包括新增的大项费用)
  194. let allFilter = []; //filter及其子项
  195. for (let flag of filter) {
  196. if (subFlagMapping[flag].length > 0) {
  197. allFilter = allFilter.concat(subFlagMapping[flag]);
  198. }
  199. }
  200. allFilter = allFilter.concat(filter);
  201. allFilter = Array.from(new Set(allFilter));
  202. //获取可使用此基数的清单固定行
  203. let validFlags = pick
  204. ? allFilter
  205. : allFlags.filter(function (flag) {
  206. return !allFilter.includes(flag);
  207. });
  208. //其他节点可使用的基数(新增的大项费用),即基数配置表中过滤条件为“只允许非固定类别是xxx”的
  209. //允许非固定类别xx可用,则新增的大项费用也可用,新增的大项费用flag为null
  210. if (!pick) {
  211. if (mapping["other"]) {
  212. mapping["other"].push(baseName);
  213. } else {
  214. mapping["other"] = [baseName];
  215. }
  216. }
  217. //设置清单固定行可使用此基数
  218. for (let flag of validFlags) {
  219. if (mapping[flag]) {
  220. mapping[flag].push(baseName);
  221. } else {
  222. mapping[flag] = [baseName];
  223. }
  224. }
  225. }
  226. },
  227. //该节点可使用的基数列表
  228. getValidFigures: function (node) {
  229. let filterMap = {},
  230. avaBaseNames = [];
  231. //该节点所属的固定行
  232. let belongFlag = this.getBelongFlag(node);
  233. //没有所属固定行,则属于新增的大项费用
  234. //获取可使用的基数
  235. if (!belongFlag) {
  236. avaBaseNames = calcBase.flagValidBase["other"];
  237. } else {
  238. avaBaseNames = calcBase.flagValidBase[belongFlag] ? calcBase.flagValidBase[belongFlag] : [];
  239. }
  240. for (let baseName of avaBaseNames) {
  241. let base = calcBase.baseFigures[baseName];
  242. if (baseName) {
  243. filterMap[baseName] = base;
  244. }
  245. }
  246. return filterMap;
  247. },
  248. //根据清单固定行,获取子固定行
  249. getSubFlagList: function (flag) {
  250. let flagList = [];
  251. let node = this.findNodeByFlag(flag);
  252. if (!node) {
  253. return flagList;
  254. }
  255. let allChildren = [];
  256. function getChildren(nodes) {
  257. allChildren = allChildren.concat(nodes);
  258. for (let node of nodes) {
  259. if (node.children.length > 0) {
  260. getChildren(node.children);
  261. }
  262. }
  263. }
  264. getChildren(node.children);
  265. for (let child of allChildren) {
  266. if (child.data && this.isFlag(child.data)) {
  267. flagList.push(child.data.flagsIndex.fixed.flag);
  268. }
  269. }
  270. return flagList;
  271. },
  272. //获取节点所属的清单固定行
  273. getBelongFlag: function (node) {
  274. while (node) {
  275. if (node.data && this.isFlag(node.data)) {
  276. return node.data.flagsIndex.fixed.flag;
  277. }
  278. node = node.parent;
  279. }
  280. return null;
  281. },
  282. //获取节点所属的清单固定列表
  283. getBelongFlagList: function (node) {
  284. let rst = [];
  285. while (node) {
  286. if (node.data && this.isFlag(node.data)) {
  287. rst.push(node.data.flagsIndex.fixed.flag);
  288. }
  289. node = node.parent;
  290. }
  291. return rst;
  292. },
  293. //获取清单(有基数计算)引用了的其他清单,(循环引用栈中的一块)
  294. getStackBlock: function (billID) {
  295. let tempBases = [],
  296. block = []; //存引用的清单ID
  297. let node = getBill(billID);
  298. if (!node) {
  299. return tempBases;
  300. } else {
  301. //获取基数和行引用
  302. getBase(node);
  303. let bases = Array.from(new Set(tempBases));
  304. //根据基数和行引用获取清单ID
  305. for (let i = 0, len = bases.length; i < len; i++) {
  306. //基数是跟清单直接关联的
  307. if (bases[i]["type"] === "base" && cbTools.isDef(calcBase.baseFigures[bases[i]["value"]])) {
  308. let figureMultiRef = calcBase.baseFigures[bases[i]["value"]]["multiRef"];
  309. let cycleCalcRef = calcBase.baseFigures[bases[i]["value"]]["cycleCalcRef"];
  310. if (cbTools.isDef(figureMultiRef)) {
  311. if (cbTools.isDef(cycleCalcRef)) {
  312. figureMultiRef = cycleCalcRef;
  313. }
  314. for (let flag of figureMultiRef) {
  315. let bills = cbTools.findBill(flag);
  316. if (cbTools.isDef(bills)) {
  317. block.push(bills.ID);
  318. }
  319. }
  320. } else if (cbTools.isDef(calcBase.baseFigures[bases[i]["value"]]["fixedBill"])) {
  321. block.push(calcBase.baseFigures[bases[i]["value"]]["fixedBill"]["bill"]["ID"]);
  322. }
  323. } else if (bases[i]["type"] === "id") {
  324. let node = cbTools.getNodeByID(bases[i]["value"]);
  325. if (cbTools.isDef(node)) {
  326. block.push(node.data.ID);
  327. }
  328. }
  329. }
  330. return Array.from(new Set(block));
  331. }
  332. function getBase(node) {
  333. if (node && node.children.length === 0) {
  334. if (cbTools.isDef(node.data.calcBase) && node.data.calcBase !== "") {
  335. let figureF = cbParser.getFigureF(cbParser.getFigure(node.data.calcBase), cbParser.getUID(cbParser.getFIDArr(node.data.calcBase)));
  336. tempBases = tempBases.concat(figureF);
  337. }
  338. } else if (node && node.children.length > 0) {
  339. for (let i = 0, len = node.children.length; i < len; i++) {
  340. getBase(node.children[i]);
  341. }
  342. }
  343. }
  344. function getBill(ID) {
  345. let nodes = calcBase.project.mainTree.nodes;
  346. let node = nodes["id_" + ID];
  347. if (cbTools.isDef(node) && node.sourceType === calcBase.project.Bills.getSourceType()) {
  348. return node;
  349. }
  350. return null;
  351. }
  352. },
  353. // 获取全部有公式的树节点清单。 CSL, 2018-01-05
  354. getFormulaNodes: function (needOrder = false) {
  355. // 给公式结点清单换照引用计算顺序排序。
  356. function orderFormulaNodes(nodesArr) {
  357. let orderArr = [];
  358. function recursionNode(nodes) {
  359. for (let node of nodes) {
  360. if (orderArr.includes(node)) continue; // 已排过序的节点则跳过
  361. if (node.data.calcBase) {
  362. let subNodes = cbTools.getNodesByExp(node, nodesArr);
  363. recursionNode(subNodes);
  364. }
  365. if (nodesArr.includes(node) && !orderArr.includes(node)) orderArr.push(node);
  366. }
  367. }
  368. recursionNode(nodesArr);
  369. return orderArr;
  370. }
  371. let nodes = [];
  372. for (let node of projectObj.project.mainTree.items) {
  373. if (node.sourceType == ModuleNames.bills && node.data.calcBase && node.data.calcBase != "") nodes.push(node);
  374. }
  375. if (needOrder && nodes.length >= 2) return orderFormulaNodes(nodes);
  376. else return nodes;
  377. },
  378. // 刷新全部行引用的公式清单。 CSL, 2018-01-05
  379. refreshFormulaNodes: function () {
  380. try {
  381. let nodes = this.getFormulaNodes();
  382. if (nodes.length > 0) projectObj.mainController.refreshTreeNode(nodes, false, false);
  383. } catch (err) {
  384. alert("公式引用行号显示刷新失败:" + err.message);
  385. }
  386. },
  387. // 判断结点是否被其它结点的表达式引用。
  388. isUsedByFormula: function (node) {
  389. let nodes = this.getFormulaNodes();
  390. if (nodes.length == 0) return false;
  391. let sID = "@" + node.data.ID;
  392. for (let node of nodes) {
  393. if (node.data.calcBase.hasSubStr(sID)) return true;
  394. }
  395. },
  396. // 获取直接关联清单节点的基数金额
  397. getBaseFee: function (flag, tender, feeField) {
  398. const subFeeField = tender ? "tenderTotalFee" : "totalFee";
  399. return this.getBillsFee(flag, feeField, subFeeField);
  400. },
  401. //获取清单节点的金额
  402. //@param {Number}fixedFlag(清单固定行类别) {String}feeField(外层金额字段: common) {String}subFeeField(子金额字段: totalFee)
  403. //@return {Number}
  404. getBillsFee: function (fixedFlag, feeField, subFeeField) {
  405. //固定清单类别与清单数据、关联基数的映射
  406. let fixedBills = calcBase.fixedBills[fixedFlag];
  407. if (this.isUnDef(fixedBills)) {
  408. return 0;
  409. }
  410. let bills = fixedBills.bill;
  411. if (this.isUnDef(bills)) {
  412. return 0;
  413. }
  414. if (this.isUnDef(bills.feesIndex) || _.isEmpty(bills.feesIndex)) {
  415. return 0;
  416. }
  417. return this.isDef(bills.feesIndex[feeField]) && this.isDef(bills.feesIndex[feeField][subFeeField]) && !isNaN(bills.feesIndex[feeField][subFeeField])
  418. ? bills.feesIndex[feeField][subFeeField]
  419. : 0;
  420. },
  421. getFee: function (bills, feeField, subFeeField) {
  422. if (this.isUnDef(bills)) {
  423. return 0;
  424. }
  425. if (this.isUnDef(bills.feesIndex) || _.isEmpty(bills.feesIndex)) {
  426. return 0;
  427. }
  428. return this.isDef(bills.feesIndex[feeField]) && this.isDef(bills.feesIndex[feeField][subFeeField]) && !isNaN(bills.feesIndex[feeField][subFeeField])
  429. ? bills.feesIndex[feeField][subFeeField]
  430. : 0;
  431. },
  432. /**
  433. * 获取扣除固定项后的金额,扣除其节点后重新汇总
  434. * @param {Number} fixedFlag - 基数取值固定行类别
  435. * @param {Array} deductFlags - 扣除的固定类别组
  436. * @param {Boolean} tender - 是否调价
  437. * @param {String} feeField - 价格字段
  438. * @param {Boolean = true} isRound - 是否取舍
  439. * @return {Number}
  440. */
  441. getFeeWithDeduction: function (fixedFlag, deductFlags, tender, feeField, isRound = true) {
  442. const fullFeeField = tender ? `${feeField}.tenderTotalFee` : `${feeField}.totalFee`;
  443. let baseNode = this.findNodeByFlag(fixedFlag);
  444. if (!baseNode) {
  445. return 0;
  446. }
  447. //要扣除的节点
  448. let deductNodes = [];
  449. for (let deFlag of deductFlags) {
  450. let node = this.findNodeByFlag(deFlag);
  451. if (node) {
  452. deductNodes.push(node);
  453. }
  454. }
  455. const fee = projectObj.project.calcProgram.getTotalFee([baseNode], deductNodes, fullFeeField);
  456. return isRound ? fee.toDecimal(decimalObj.bills.totalPrice) : fee;
  457. },
  458. /* getFeeWithDeduction: function (fixedFlag, deductFlags, fullFeeField) {
  459. let baseNode = this.findNodeByFlag(fixedFlag);
  460. if (!baseNode) {
  461. return 0;
  462. }
  463. //要扣除的节点
  464. let deductNodes = [];
  465. for (let deFlag of deductFlags) {
  466. let node = this.findNodeByFlag(deFlag);
  467. if (node) {
  468. deductNodes.push(node);
  469. }
  470. }
  471. return projectObj.project.calcProgram.getTotalFee([baseNode], deductNodes, fullFeeField);
  472. }, */
  473. //获取累进办法计算的金额
  474. //@param {Number}baseFee(相关基数金额) {String}name(使用累进计算的基数名称)
  475. //@return {Number}
  476. getProgressiveFee: function (baseFee, name) {
  477. const progressiveData = calcBase.project.property.progressiveInterval;
  478. if (!progressiveData) {
  479. throw "该项目不存在累进区间数据";
  480. }
  481. //根据基数名称匹配累进库数据,标准化以免(())等不同导致不匹配
  482. const matchProgressiveData = progressiveData.find((item) => cbAnalyzer.standar(item.name) === cbAnalyzer.standar(name));
  483. if (!matchProgressiveData) {
  484. throw `计算基数{${name}}不存在累进区间数据`;
  485. }
  486. // 将原始数据转换成方便处理的数据:[{feeRate: xx, min: 0, max: 200, minOpr: '(', maxOpr: ']'}]
  487. const progression = matchProgressiveData.progression.map((item) => {
  488. // item.interval内容: eg (0,200]、[300,500) [1000,+)....
  489. const interval = cbAnalyzer.standar(item.interval);
  490. // ( => 大于 [ => 大于等于 ) => 小于 ] => 小于等于
  491. const minReg = /([\(\[])(\d+)/;
  492. const minMatch = minReg.exec(interval);
  493. if (!minMatch || !minMatch[1] || !minMatch[2]) {
  494. throw `计算基数{${name}}累进区间数据错误`;
  495. }
  496. const minOpr = minMatch[1];
  497. // 后台数据单位为万元,这里转为为元
  498. const min = parseFloat(minMatch[2]) * 10000;
  499. const maxReg = /[\,,]([\d\+]+)([\)\]])/;
  500. const maxMatch = maxReg.exec(interval);
  501. if (!maxMatch || !maxMatch[1] || !maxMatch[2]) {
  502. throw `计算基数{${name}}累进区间数据错误`;
  503. }
  504. const max = maxMatch[1] === "+" ? "infinity" : parseFloat(maxMatch[1]) * 10000;
  505. const maxOpr = maxMatch[2];
  506. return {
  507. feeRate: item.feeRate,
  508. min,
  509. minOpr,
  510. max,
  511. maxOpr,
  512. };
  513. });
  514. progression.sort((a, b) => a.min - b.min);
  515. // 基数所在区间
  516. const withinData = progression.find((item) => {
  517. const oprMiddle = item.max === "infinity" ? "+" : "";
  518. const oprLink = item.minOpr + oprMiddle + item.maxOpr;
  519. switch (oprLink) {
  520. case "()":
  521. return baseFee > item.min && baseFee < item.max;
  522. case "(]":
  523. return baseFee > item.min && baseFee <= item.max;
  524. case "[)":
  525. return baseFee >= item.min && baseFee < item.max;
  526. case "[]":
  527. return baseFee >= item.min && baseFee <= item.max;
  528. case "(+)":
  529. case "(+]":
  530. return baseFee > item.min;
  531. case "[+)":
  532. case "[+]":
  533. return baseFee >= item.min;
  534. default:
  535. return false;
  536. }
  537. });
  538. if (!withinData) {
  539. return 0;
  540. }
  541. // 累进计算
  542. let fee = 0;
  543. //累进之前的区间
  544. for (let i = 0; i < progression.indexOf(withinData); i++) {
  545. const perData = progression[i];
  546. fee += (perData.max - perData.min) * perData.feeRate * 0.01;
  547. }
  548. //累进所在区间
  549. fee += (baseFee - withinData.min) * withinData.feeRate * 0.01;
  550. return fee.toDecimal(decimalObj.bills.totalPrice);
  551. },
  552. // 获取设备购置费
  553. getEquipmentFee(fixedNode, tender, feeField = "common") {
  554. const allSubNodes = [];
  555. projectObj.project.mainTree.getAllSubNode(fixedNode, allSubNodes);
  556. let equipmentNodes = allSubNodes.filter((node) => node.data.type === rationType.gljRation && node.data.subType === gljType.EQUIPMENT);
  557. if (!isLowVer(historyVer1)) equipmentNodes = cleanDirtyData(equipmentNodes); // 旧项目,为保证数据不变,将错就错,不过滤脏数据。
  558. const subFeeField = tender ? "tenderTotalFee" : "totalFee";
  559. let totalEquipmentFee = 0;
  560. for (const node of equipmentNodes) {
  561. const data = node.data;
  562. if (
  563. this.isUnDef(data.feesIndex) ||
  564. _.isEmpty(data.feesIndex) ||
  565. this.isUnDef(data.feesIndex[feeField]) ||
  566. this.isUnDef(data.feesIndex[feeField][subFeeField])
  567. ) {
  568. continue;
  569. }
  570. totalEquipmentFee = (totalEquipmentFee + data.feesIndex[feeField][subFeeField]).toDecimal(decimalObj.process);
  571. }
  572. return totalEquipmentFee;
  573. },
  574. //获取清单100章下的节点(只需要找最底层的,排除了底层,父项金额即排除了子项)
  575. //@param {Object}node(判断的节点,最底层清单节点)
  576. //@return {Boolean}
  577. withingOneHundred: function (node) {
  578. if (!node || node.sourceType !== calcBase.project.Bills.getSourceType() || node.source.children.length > 0) {
  579. return false;
  580. }
  581. //节点所属的清单固定行为第100章清单
  582. let belongFlags = cbTools.getBelongFlagList(node);
  583. return belongFlags.includes(fixedFlag.ONE_HUNDRED_BILLS);
  584. },
  585. };
  586. let baseFigureTemplate = {
  587. /*
  588. * 预算项目
  589. * */
  590. budget: {
  591. //{定额建筑安装工程费(不含定额设备购置费及专项费用)}
  592. //取清单固定类别是“建筑安装工程”的定额建安费,但要扣除清单固定类别是“设备购置费”、及“专项费用”的定额建安费
  593. DEJZAZGCFBHSBZX: function (tender) {
  594. const deductFlags = [fixedFlag.EQUIPMENT_ACQUISITION_FEE, fixedFlag.SPECIAL_COST];
  595. return cbTools.getFeeWithDeduction(fixedFlag.CONSTRUCTION_INSTALL_FEE, deductFlags, tender, "rationCommon");
  596. },
  597. //{定额建筑安装工程(其中定额设备购置费按 40%计)} (定额建筑安装工程设备四十)
  598. //扣除设备购置费,再加上设备购置费的40%,扣除汇总算法不四舍五入,相当于汇总当中定额设备购置费就按照了40%计
  599. DEJZAZGCSBSS: function (tender) {
  600. const feeField = "rationCommon";
  601. const deductFlags = [fixedFlag.EQUIPMENT_ACQUISITION_FEE];
  602. //建安费扣除定额设备购置费
  603. const afterDeductFee = cbTools.getFeeWithDeduction(fixedFlag.CONSTRUCTION_INSTALL_FEE, deductFlags, tender, feeField, false);
  604. //定额设备购置费
  605. let equipmentAcFee = cbTools.getBaseFee(deductFlags[0], tender, feeField);
  606. return (afterDeductFee + equipmentAcFee * 0.4).toDecimal(decimalObj.bills.totalPrice);
  607. },
  608. //{建筑安装工程费(不含安全生产费)}
  609. // 取清单固定类别是“建筑安装工程”的金额,但要扣除清单固定类别是“安全生产费”的金额
  610. JZAZGCFBHSC: function (tender) {
  611. //建安费扣除安全生产费
  612. return cbTools.getFeeWithDeduction(fixedFlag.CONSTRUCTION_INSTALL_FEE, [fixedFlag.SAFE_COST], tender, "common");
  613. },
  614. //{建筑安装工程费(不含设备费)}
  615. // 取清单固定类别是“建筑安装工程”的金额,但要扣除清单固定类别是“设备购置费”的金额
  616. JZAZGCFBHSB: function (tender) {
  617. //建安费扣除设备费
  618. return cbTools.getFeeWithDeduction(fixedFlag.CONSTRUCTION_INSTALL_FEE, [fixedFlag.EQUIPMENT_ACQUISITION_FEE], tender, "common");
  619. },
  620. //{建筑安装工程费}
  621. // 取清单固定类别是“建筑安装工程”的金额
  622. JZAZGCF: function (tender) {
  623. return cbTools.getBaseFee(calcBase.fixedFlag.CONSTRUCTION_INSTALL_FEE, tender, "common");
  624. },
  625. //{土地使用及拆迁补偿费}
  626. // 取清单固定类别是“土地使用及拆迁补偿费”的金额
  627. TDSYJCQBCF: function (tender) {
  628. return cbTools.getBaseFee(calcBase.fixedFlag.LAND_USED_DEMOLITION, tender, "common");
  629. },
  630. //{养护工程其他费}
  631. // 取清单固定类别是“养护工程其他费”的金额
  632. YHGCQTF: function (tender) {
  633. return cbTools.getBaseFee(calcBase.fixedFlag.MAINTENANCE_EXPENSES, tender, "common");
  634. },
  635. //{预备费}
  636. // 取清单固定类别是“预备费”的金额
  637. YBF: function (tender) {
  638. return cbTools.getBaseFee(calcBase.fixedFlag.BUDGET_FEE, tender, "common");
  639. },
  640. //{施工场地建设费}
  641. //使用累进办法计算,基数为{定额建筑安装工程费(不含定额设备购置费及专项费用)}
  642. SGCDJSF: function (tender) {
  643. let baseFee = this["DEJZAZGCFBHSBZX"](tender);
  644. if (!tender) {
  645. calcBase.baseProgressiveFee = baseFee;
  646. }
  647. return calculateUtil.getProgressiveFee(
  648. baseFee,
  649. "施工场地建设费",
  650. projectObj.project.property.progressiveInterval,
  651. decimalObj.bills.totalPrice,
  652. deficiency
  653. );
  654. },
  655. //{养护单位(业主)管理费}
  656. // 使用累进办法计算,计算基数为{定额建筑安装工程(其中定额设备购置费按 40%计)}
  657. YHDWYZGLF: function (tender) {
  658. let baseFee = this["DEJZAZGCSBSS"](tender);
  659. if (!tender) {
  660. calcBase.baseProgressiveFee = baseFee;
  661. }
  662. return calculateUtil.getProgressiveFee(
  663. baseFee,
  664. "养护单位(业主)管理费",
  665. projectObj.project.property.progressiveInterval,
  666. decimalObj.bills.totalPrice,
  667. deficiency
  668. );
  669. },
  670. //{信息化费}
  671. // 使用累进办法计算,计算基数为{定额建筑安装工程(其中定额设备购置费按 40%计)}
  672. XXHF: function (tender) {
  673. let baseFee = this["DEJZAZGCSBSS"](tender);
  674. if (!tender) {
  675. calcBase.baseProgressiveFee = baseFee;
  676. }
  677. return calculateUtil.getProgressiveFee(baseFee, "信息化费", projectObj.project.property.progressiveInterval, decimalObj.bills.totalPrice, deficiency);
  678. },
  679. //{路线工程监理费}
  680. //使用累进办法计算,不足2万按2万,计算基数为{定额建筑安装工程(其中定额设备购置费按 40%计)}
  681. LXGCJLF: function (tender) {
  682. let baseFee = this["DEJZAZGCSBSS"](tender);
  683. if (!tender) {
  684. calcBase.baseProgressiveFee = baseFee;
  685. }
  686. return calculateUtil.getProgressiveFee(
  687. baseFee,
  688. "路线工程监理费",
  689. projectObj.project.property.progressiveInterval,
  690. decimalObj.bills.totalPrice,
  691. deficiency
  692. );
  693. },
  694. //{独立桥梁隧道工程监理费}
  695. //使用累进办法计算,不足2万按2万,计算基数为{定额建筑安装工程(其中定额设备购置费按 40%计)}
  696. QLSDGCJLF: function (tender) {
  697. let baseFee = this["DEJZAZGCSBSS"](tender);
  698. if (!tender) {
  699. calcBase.baseProgressiveFee = baseFee;
  700. }
  701. return calculateUtil.getProgressiveFee(
  702. baseFee,
  703. "独立桥梁隧道工程监理费",
  704. projectObj.project.property.progressiveInterval,
  705. decimalObj.bills.totalPrice,
  706. deficiency
  707. );
  708. },
  709. //{设计文件审查费}
  710. // 使用累进办法计算,不足3千按3千,计算基数为{定额建筑安装工程(其中定额设备购置费按 40%计)}
  711. SJWJSCF: function (tender) {
  712. let baseFee = this["DEJZAZGCSBSS"](tender);
  713. if (!tender) {
  714. calcBase.baseProgressiveFee = baseFee;
  715. }
  716. return calculateUtil.getProgressiveFee(
  717. baseFee,
  718. "设计文件审查费",
  719. projectObj.project.property.progressiveInterval,
  720. decimalObj.bills.totalPrice,
  721. deficiency
  722. );
  723. },
  724. //{路线勘察设计费}
  725. // 使用累进办法计算,计算基数为{定额建筑安装工程(其中定额设备购置费按 40%计)}
  726. LXKCSJF: function (tender) {
  727. let baseFee = this["DEJZAZGCSBSS"](tender);
  728. if (!tender) {
  729. calcBase.baseProgressiveFee = baseFee;
  730. }
  731. return calculateUtil.getProgressiveFee(
  732. baseFee,
  733. "路线勘察设计费",
  734. projectObj.project.property.progressiveInterval,
  735. decimalObj.bills.totalPrice,
  736. deficiency
  737. );
  738. },
  739. //{独立桥梁隧道维修加固勘察设计费}
  740. // 使用累进办法计算,计算基数为{定额建筑安装工程(其中定额设备购置费按 40%计)}
  741. QLSDKCSJF: function (tender) {
  742. let baseFee = this["DEJZAZGCSBSS"](tender);
  743. if (!tender) {
  744. calcBase.baseProgressiveFee = baseFee;
  745. }
  746. return calculateUtil.getProgressiveFee(
  747. baseFee,
  748. "独立桥梁隧道维修加固勘察设计费",
  749. projectObj.project.property.progressiveInterval,
  750. decimalObj.bills.totalPrice,
  751. deficiency
  752. );
  753. },
  754. //{招标代理及标底(最高投标限价)编制费} (招标代理及标底编制费ZBDLJBDBZF)
  755. // 使用累进办法计算,计算基数为{定额建筑安装工程(其中定额设备购置费按 40%计)}
  756. ZBDLJBDBZF: function (tender) {
  757. let baseFee = this["DEJZAZGCSBSS"](tender);
  758. if (!tender) {
  759. calcBase.baseProgressiveFee = baseFee;
  760. }
  761. return calculateUtil.getProgressiveFee(
  762. baseFee,
  763. "招标代理及标底(最高投标限价)编制费",
  764. projectObj.project.property.progressiveInterval,
  765. decimalObj.bills.totalPrice,
  766. deficiency
  767. );
  768. },
  769. //{价差预备费}
  770. //以建筑安装工程费为基数
  771. JCYBF: function (tender) {
  772. //建筑安装工程费作为基数
  773. let installFee = this["JZAZGCF"](tender);
  774. //年造价增涨
  775. let costGrowthRate = calcBase.project.property.costGrowthRate ? calcBase.project.property.costGrowthRate : 0;
  776. //增涨计费年限
  777. let growthPeriod = projectObj.project.property.growthPeriod ? calcBase.project.property.growthPeriod : 0;
  778. //= P * [(1+i)^(n-1) -1]
  779. return (installFee * (Math.pow(1 + costGrowthRate, growthPeriod - 1) - 1)).toDecimal(decimalObj.bills.totalPrice);
  780. },
  781. },
  782. /*
  783. * 工程量清单项目(bills of quantities)
  784. * */
  785. boq: {
  786. //{各章清单合计}
  787. // 取清单固定类别是“第100章至700章清单”的金额
  788. GZQDHJ: function (tender) {
  789. let feeField = "common",
  790. subFeeField = tender ? "tenderTotalFee" : "totalFee";
  791. return cbTools.getBillsFee(calcBase.fixedFlag.ONE_SEVEN_BILLS, feeField, subFeeField);
  792. },
  793. //{专项暂定合计}
  794. // 汇总专项暂定列有值的清单的金额
  795. /* 'ZXZDHJ': function (tender) {
  796. let rst = 0,
  797. feeField = 'common',
  798. subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
  799. let billsData = calcBase.project.Bills.datas,
  800. filterData = billsData.filter(function (data) {
  801. return data.specialProvisional;
  802. });
  803. for (let data of filterData) {
  804. if (cbTools.isUnDef(data.feesIndex) || _.isEmpty(data.feesIndex) ||
  805. cbTools.isUnDef(data.feesIndex[feeField]) || cbTools.isUnDef(data.feesIndex[feeField][subFeeField])) {
  806. continue;
  807. }
  808. rst += data.feesIndex[feeField][subFeeField];
  809. }
  810. return rst.toDecimal(decimalObj.bills.totalPrice);
  811. }, */
  812. // 第100章至700章清单行的暂估合价
  813. ZXZDHJ: function (tender) {
  814. return cbTools.getBaseFee(calcBase.fixedFlag.ONE_SEVEN_BILLS, tender, "estimate");
  815. },
  816. //{100章以外清单合计}
  817. // 取清单固定清单[第100章至700章清单]的金额,但扣除清单100章下的金额。
  818. // 如果是固定清单[第100章至700章清单]下100章以外清单引用此基数,要排除自身(目前只允许100章的清单使用,所以暂时不需要此判断)
  819. YBZYHQDHJ: function (tender) {
  820. let oneToSeven = cbTools.findNodeByFlag(fixedFlag.ONE_SEVEN_BILLS);
  821. if (!oneToSeven) {
  822. return 0;
  823. }
  824. //100-700章固定节点的所有子节点
  825. let allChildren = [];
  826. function getChildren(nodes) {
  827. allChildren = allChildren.concat(nodes);
  828. for (let node of nodes) {
  829. if (node.children.length > 0) {
  830. getChildren(node.children);
  831. }
  832. }
  833. }
  834. getChildren(oneToSeven.children);
  835. //扣除的节点:100章的节点[100-200)
  836. let deductNodes = allChildren.filter(cbTools.withingOneHundred);
  837. //计算金额
  838. let fullFeeField = tender ? "common.tenderTotalFee" : "common.totalFee";
  839. return projectObj.project.calcProgram.getTotalFee([oneToSeven], deductNodes, fullFeeField).toDecimal(decimalObj.bills.totalPrice);
  840. },
  841. // 清单项目基数:{定额建筑安装工程费} 算法:取清单固定类别是“第100章至700章清单”的定额建安费(其中定额设备费按40%计算,税金是全额计算。公路云默认要使用此算法)。
  842. // 显示:只有清单固定类别是“第100章清单总则”的部分可显示。
  843. DEJZAZGCF(tender) {
  844. const baseFee = cbTools.getBaseFee(fixedFlag.ONE_SEVEN_BILLS, tender, "rationCommon");
  845. const fixedNode = projectObj.project.mainTree.roots.find((node) => node.getFlag() === fixedFlag.ONE_SEVEN_BILLS);
  846. const equipmentFee = cbTools.getEquipmentFee(fixedNode, tender, "equipment");
  847. return (baseFee - equipmentFee * 0.6).toDecimal(decimalObj.bills.totalPrice);
  848. },
  849. },
  850. };
  851. //基数的值不是通过直接引用某清单节点获得的,则该基数的fixedBill为空,如价差、甲供、分包; class:分类,用于基数选择界面分类显示
  852. //基数本身不与清单节点关联、但是其由与清单关联的节点四则运算得到,则拥有字段multiRef: [flags...]
  853. /*
  854. * 基数的过滤filter ,根据这个配置最终可以转换成清单固定行可使用的相应基数
  855. * 筛选和过滤由pick决定
  856. * 控制基数可被哪些清单固定行下的节点使用 //挑选 pick === true
  857. * 控制基数不可被哪些清单固定行下的节点使用 //过滤 pick === false
  858. * */
  859. //暂时特殊处理专项费用需要引用{定额建筑安装工程费(其中定额设备购置费按40%计)}等跟专项费用父项有关联的基数:将fixedFlag设置为null
  860. let baseFigureMap = {
  861. /*
  862. * 预算项目
  863. * */
  864. budget: {
  865. //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
  866. "定额建筑安装工程费(不含定额设备购置费及专项费用)": {
  867. base: "DEJZAZGCFBHSBZX",
  868. fixedFlag: null,
  869. filter: [fixedFlag.SPECIAL_COST, fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
  870. pick: true,
  871. },
  872. "定额建筑安装工程费(其中定额设备购置费按40%计)": {
  873. base: "DEJZAZGCSBSS",
  874. fixedFlag: null,
  875. filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
  876. pick: true,
  877. },
  878. //只允许固定类别是“安全生产费”
  879. "建筑安装工程费(不含安全生产费)": {
  880. base: "JZAZGCFBHSC",
  881. fixedFlag: null,
  882. filter: [fixedFlag.SAFE_COST],
  883. pick: true,
  884. },
  885. //只允许固定类别是“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
  886. "建筑安装工程费(不含设备费)": {
  887. base: "JZAZGCFBHSB",
  888. fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
  889. filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
  890. pick: true,
  891. },
  892. //只允许非固定类别是“建筑安装工程费”下的清单引用
  893. 建筑安装工程费: {
  894. base: "JZAZGCF",
  895. fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
  896. filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE],
  897. pick: false,
  898. },
  899. //只允许非固定类别是“建筑安装工程费”、非固定类别是“土地使用及拆迁补偿费”下的清单引用
  900. 土地使用及拆迁补偿费: {
  901. base: "TDSYJCQBCF",
  902. fixedFlag: fixedFlag.LAND_USED_DEMOLITION,
  903. filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE, fixedFlag.LAND_USED_DEMOLITION],
  904. pick: false,
  905. },
  906. //只允许非固定类别是“建筑安装工程费”、非固定类别是“土地使用及拆迁补偿费”、非固定类别是“养护工程其他费”下的清单引用
  907. 养护工程其他费: {
  908. base: "YHGCQTF",
  909. fixedFlag: fixedFlag.MAINTENANCE_EXPENSES,
  910. filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE, fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
  911. pick: false,
  912. },
  913. //只允许非固定类别是“建筑安装工程费”、非固定类别是“土地使用及拆迁补偿费”、非固定类别是“养护工程其他费”、非固定类别是“预备费”下的清单引用。
  914. 预备费: {
  915. base: "YBF",
  916. fixedFlag: fixedFlag.BUDGET_FEE,
  917. filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE, fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES, fixedFlag.BUDGET_FEE],
  918. pick: false,
  919. },
  920. //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
  921. 施工场地建设费: {
  922. base: "SGCDJSF",
  923. fixedFlag: null,
  924. filter: [fixedFlag.SPECIAL_COST, fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
  925. pick: true,
  926. },
  927. //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
  928. "养护单位(业主)管理费": {
  929. base: "YHDWYZGLF",
  930. fixedFlag: null,
  931. filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
  932. pick: true,
  933. },
  934. //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
  935. 信息化费: {
  936. base: "XXHF",
  937. fixedFlag: null,
  938. filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
  939. pick: true,
  940. },
  941. //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
  942. 路线工程监理费: {
  943. base: "LXGCJLF",
  944. fixedFlag: null,
  945. filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
  946. pick: true,
  947. },
  948. //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
  949. 独立桥梁隧道工程监理费: {
  950. base: "QLSDGCJLF",
  951. fixedFlag: null,
  952. filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
  953. pick: true,
  954. },
  955. //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
  956. 设计文件审查费: {
  957. base: "SJWJSCF",
  958. fixedFlag: null,
  959. filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
  960. pick: true,
  961. },
  962. //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
  963. 路线勘察设计费: {
  964. base: "LXKCSJF",
  965. fixedFlag: null,
  966. filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
  967. pick: true,
  968. },
  969. //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
  970. 独立桥梁隧道维修加固勘察设计费: {
  971. base: "QLSDKCSJF",
  972. fixedFlag: null,
  973. filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
  974. pick: true,
  975. },
  976. "招标代理及标底(最高投标限价)编制费": {
  977. base: "ZBDLJBDBZF",
  978. fixedFlag: null,
  979. filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
  980. pick: true,
  981. },
  982. //只允许固定类别是“价差预备费”的清单使用
  983. 价差预备费: {
  984. base: "JCYBF",
  985. fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
  986. filter: [fixedFlag.SPREAD_BUDGET_FEE],
  987. pick: true,
  988. },
  989. },
  990. /*
  991. * 工程量清单项目
  992. * */
  993. boq: {
  994. //仅允许用于固定类别是“第100章至700章清单”以外的清单
  995. 各章清单合计: {
  996. base: "GZQDHJ",
  997. fixedFlag: fixedFlag.ONE_SEVEN_BILLS,
  998. filter: [fixedFlag.ONE_SEVEN_BILLS],
  999. pick: false,
  1000. },
  1001. //仅允许用于固定类别是“第100章至700章清单”以外的清单
  1002. 专项暂定合计: {
  1003. base: "ZXZDHJ",
  1004. fixedFlag: null,
  1005. filter: [fixedFlag.ONE_SEVEN_BILLS],
  1006. pick: false,
  1007. },
  1008. /*
  1009. * 清单固定行[第100章至700章清单]下的[第100章清单]需要允许清单可使用基数{100章以外合计}
  1010. * 因此{100章以外合计}不设置关联的清单固定行
  1011. * */
  1012. //仅允许用于固定类别为“100章清单”引用
  1013. "100章以外清单合计": {
  1014. base: "YBZYHQDHJ",
  1015. fixedFlag: null,
  1016. filter: [fixedFlag.ONE_HUNDRED_BILLS],
  1017. pick: true,
  1018. },
  1019. // 各部分都能用
  1020. "定额建安费(不含定额设备购置费)": {
  1021. base: "DEJAFBHDESBGZF",
  1022. fixedFlag: null,
  1023. filter: null,
  1024. pick: true,
  1025. },
  1026. },
  1027. };
  1028. //输入式分析器
  1029. let cbAnalyzer = {
  1030. standar: function (exp) {
  1031. //去空格
  1032. exp = exp.replace(/\s/g, "");
  1033. //( to (
  1034. exp = exp.replace(/(/g, "(");
  1035. //)to )
  1036. exp = exp.replace(/)/g, ")");
  1037. //,to ,
  1038. exp = exp.replace(/,/g, ",");
  1039. //f to F
  1040. exp = exp.replace(new RegExp("f", "g"), "F");
  1041. return exp;
  1042. },
  1043. //输入合法性
  1044. inputLegal: function (exp) {
  1045. let ilegalRex = /[^0-9,\u4e00-\u9fa5,\+,\-,\/,\*,\(,\),.,{,},F,%、]/g;
  1046. return !ilegalRex.test(exp);
  1047. },
  1048. //基数合法性、存在性
  1049. baseLegal: function (baseFigures, exp) {
  1050. //保证中文表达式在{}里
  1051. let cnExps = cbParser.getCN(exp);
  1052. let expFigures = cbParser.getFigure(exp);
  1053. if (cnExps.length !== expFigures.length) {
  1054. throw "清单基数必须要用花括号{}括起来";
  1055. return false;
  1056. }
  1057. for (let i = 0, len = cnExps.length; i < len; i++) {
  1058. if (cnExps[i] !== expFigures[i]) {
  1059. throw "清单基数必须要用花括号{}括起来";
  1060. return false;
  1061. }
  1062. }
  1063. //基数存在性
  1064. for (let i = 0, len = expFigures.length; i < len; i++) {
  1065. if (cbTools.isUnDef(baseFigures[expFigures[i]])) {
  1066. throw `清单基数{${expFigures[i]}}不存在`;
  1067. return false;
  1068. }
  1069. }
  1070. return true;
  1071. },
  1072. //行引用合法性、存在性
  1073. fLegal: function (items, exp) {
  1074. //提取F标记
  1075. let fmArr = cbParser.getFMArr(exp);
  1076. //提取行引用
  1077. let fArr = cbParser.getFArr(exp);
  1078. if (fmArr.length !== fArr.length) {
  1079. return false;
  1080. }
  1081. //提取行数
  1082. let rArr = cbParser.getXNum(fArr);
  1083. if (fArr.length !== rArr.length) {
  1084. return false;
  1085. }
  1086. rArr = Array.from(new Set(rArr));
  1087. //判断合法性和存在性
  1088. for (let i = 0, len = rArr.length; i < len; i++) {
  1089. let idx = rArr[i] - 1;
  1090. if (cbTools.isUnDef(cbTools.getBillByRow(items, idx))) {
  1091. return false;
  1092. }
  1093. }
  1094. return true;
  1095. },
  1096. //循环计算
  1097. cycleCalc: function (node, baseFigures, exp) {
  1098. let stack = [];
  1099. if (node.sourceType !== calcBase.project.Bills.getSourceType()) {
  1100. return false;
  1101. }
  1102. //用于判断的起始清单ID
  1103. let sIDs = cbTools.getNodeIDs(cbTools.getParents(node));
  1104. let figureF = cbParser.getFigureF(cbParser.getFigure(exp), cbParser.getUID(cbParser.getFIDArr(exp)));
  1105. for (let i = 0, len = figureF.length; i < len; i++) {
  1106. let figure = figureF[i];
  1107. let billsIDs = [];
  1108. if (figure.type === "base" && cbTools.isDef(baseFigures[figure.value])) {
  1109. //多重引用基数
  1110. let figureMultiRef = baseFigures[figure.value]["multiRef"];
  1111. let cycleCalcRef = baseFigures[figure.value]["cycleCalcRef"];
  1112. if (cbTools.isDef(figureMultiRef)) {
  1113. if (cbTools.isDef(cycleCalcRef)) {
  1114. figureMultiRef = cycleCalcRef;
  1115. }
  1116. for (let flag of figureMultiRef) {
  1117. let bills = cbTools.findBill(flag);
  1118. if (bills) {
  1119. billsIDs.push(bills.ID);
  1120. }
  1121. }
  1122. } else {
  1123. billsIDs = cbTools.isDef(baseFigures[figure.value]["fixedBill"]) ? [baseFigures[figure.value]["fixedBill"]["bill"]["ID"]] : [];
  1124. }
  1125. } else if (figure.type === "id") {
  1126. let node = cbTools.getNodeByID(figure.value);
  1127. billsIDs = cbTools.isDef(node) ? [node.data.ID] : [];
  1128. }
  1129. if (cbTools.isDef(billsIDs) && billsIDs.length > 0 && isCycle(billsIDs)) {
  1130. console.log("循环计算");
  1131. calcBase.errMsg = "表达式出现循环计算";
  1132. return true;
  1133. }
  1134. }
  1135. return false;
  1136. function checkStack(stack, sIDs) {
  1137. //引用栈发现了初始引用
  1138. for (let i = 0, len = sIDs.length; i < len; i++) {
  1139. if (stack.indexOf(sIDs[i]) !== -1) {
  1140. return true;
  1141. }
  1142. }
  1143. return false;
  1144. }
  1145. function isCycle(billIDs) {
  1146. stack = Array.from(new Set(stack.concat(billIDs)));
  1147. if (checkStack(stack, sIDs)) {
  1148. return true;
  1149. }
  1150. for (let i = 0, len = billIDs.length; i < len; i++) {
  1151. let block = cbTools.getStackBlock(billIDs[i]);
  1152. if (block.length > 0) {
  1153. stack = Array.from(new Set(stack.concat(block)));
  1154. let cycleFlag = isCycle(block);
  1155. if (cycleFlag === true) {
  1156. return cycleFlag;
  1157. }
  1158. //return isCycle(block);
  1159. }
  1160. }
  1161. return false;
  1162. }
  1163. },
  1164. //四则运算合法性,控制不允许重复出现运算符,这里再判断一次,控制行引用只能F
  1165. arithmeticLegal: function (exp) {
  1166. let ilegalRex = /[\+,\-,\*,\/]{2}/g;
  1167. let rex2 = /[{]{2}/g;
  1168. let rex3 = /[}]{2}/g;
  1169. let rex4 = /[F]{2}/g;
  1170. let rex5 = /[.]{2}/g;
  1171. let rex6 = /[%]{2}/g;
  1172. return !ilegalRex.test(exp) && !rex2.test(exp) && !rex3.test(exp) && !rex4.test(exp) && !rex5.test(exp) && !rex6.test(exp);
  1173. },
  1174. //
  1175. legalExp: function (node) {
  1176. let exp = this.standar(node.data.userCalcBase);
  1177. if (!this.inputLegal(exp)) {
  1178. throw "表达式含有无效字符";
  1179. }
  1180. if (!this.arithmeticLegal(exp)) {
  1181. throw "表达式含有无效字符";
  1182. }
  1183. if (!this.baseLegal(cbTools.getValidFigures(node), exp)) {
  1184. throw "清单基数不合法";
  1185. }
  1186. if (!this.fLegal(calcBase.project.mainTree.items, exp)) {
  1187. throw "行引用不合法";
  1188. }
  1189. //转换成ID引用
  1190. exp = cbParser.toIDExpr(exp);
  1191. if (this.cycleCalc(node, calcBase.baseFigures, exp)) {
  1192. throw "出现循环计算";
  1193. }
  1194. return exp;
  1195. },
  1196. };
  1197. //输入式转换器
  1198. let cbParser = {
  1199. //获取标记F
  1200. getFMArr: function (exp) {
  1201. let fmRex = /F/g;
  1202. let fmArr = exp.match(fmRex);
  1203. return cbTools.isDef(fmArr) ? fmArr : [];
  1204. },
  1205. //获取行引用 eg: F10
  1206. getFArr: function (exp) {
  1207. let fRex = /F\d+\b/g;
  1208. let fArr = exp.match(fRex);
  1209. return cbTools.isDef(fArr) ? fArr : [];
  1210. },
  1211. //获取X+num eg: F10 10 @105 105
  1212. getXNum: function (arr) {
  1213. let rRex = /\d+/g;
  1214. let tempArr = [];
  1215. for (let i = 0, len = arr.length; i < len; i++) {
  1216. tempArr = tempArr.concat(arr[i].match(rRex));
  1217. }
  1218. return tempArr;
  1219. //let rArr = Array.from(new Set(tempArr));
  1220. //return rArr;
  1221. },
  1222. //获取uuid
  1223. getUID: function (arr) {
  1224. let rRex = /[\d,a-z,A-Z,-]{36}/g;
  1225. let tempArr = [];
  1226. for (let i = 0, len = arr.length; i < len; i++) {
  1227. tempArr = tempArr.concat(arr[i].match(rRex));
  1228. }
  1229. let rArr = Array.from(new Set(tempArr));
  1230. return rArr;
  1231. },
  1232. //获取ID引用
  1233. getFIDArr: function (exp) {
  1234. return scMathUtil.getFIDArr(exp); //统一前后端调用方法
  1235. },
  1236. //获取表达式中的中文式
  1237. getCN: function (expr) {
  1238. //let cnRex = /\d*[\u4e00-\u9fa5]{1,}\({0,}[\u4e00-\u9fa5]{0,}\*?\d*%*、?[\u4e00-\u9fa5]{0,}\){0,}[\u4e00-\u9fa5]{0,}/g;
  1239. let cnRex = /\d*[\u4e00-\u9fa5]{1,}\({0,}[\u4e00-\u9fa5]{0,}\*?\d*%*、?[\u4e00-\u9fa5]{0,}\){0,}[\u4e00-\u9fa5]{0,}\(?[\u4e00-\u9fa5]{0,}\)?/g;
  1240. return _.filter(expr.match(cnRex), function (data) {
  1241. return data;
  1242. });
  1243. },
  1244. //获取表达式中的基数
  1245. getFigure: function (expr) {
  1246. let rst = [];
  1247. let rex = /\{([^}]*)\}/g;
  1248. let temp = expr.match(rex);
  1249. if (cbTools.isDef(temp)) {
  1250. for (let i = 0, len = temp.length; i < len; i++) {
  1251. rst.push(temp[i].replace(/[{,}]/g, ""));
  1252. }
  1253. }
  1254. return rst;
  1255. },
  1256. //获取表达式中的基数和ID引用
  1257. getFigureF: function (figures, fidArr) {
  1258. let rst = [];
  1259. for (let i = 0, len = figures.length; i < len; i++) {
  1260. let obj = Object.create(null);
  1261. obj.type = "base";
  1262. obj.value = figures[i];
  1263. rst.push(obj);
  1264. }
  1265. for (let i = 0, len = fidArr.length; i < len; i++) {
  1266. let obj = Object.create(null);
  1267. obj.type = "id";
  1268. obj.value = fidArr[i];
  1269. rst.push(obj);
  1270. }
  1271. return rst;
  1272. },
  1273. //表达式中的百分数转换成小数
  1274. percentToNum: function (exp) {
  1275. // let rex = /[\+,\-,\*,\/]{1}\d+(\.\d+)?%[\u4e00-\u9fa5]{0}\'{0}\){0}/g;
  1276. let rex = /[\+,\-,\*,\/]{1}\d+(\.\d+)?%(?![\u4e00-\u9fa5]|\))/g;
  1277. let percents = exp.match(rex);
  1278. let numRex = /\d+(\.\d+)?/g;
  1279. if (cbTools.isDef(percents)) {
  1280. for (let i = 0, len = percents.length; i < len; i++) {
  1281. let percentNum = percents[i].match(numRex),
  1282. oprtor = percents[i].replace(`${percentNum}%`, "");
  1283. if (cbTools.isDef(percentNum) && percentNum.length === 1) {
  1284. exp = exp.replace(new RegExp(`\\${percents[i]}`, "g"), `${oprtor}${percentNum[0] / 100}`);
  1285. }
  1286. }
  1287. }
  1288. return exp;
  1289. },
  1290. //将行引用转换成ID引用
  1291. toIDExpr: function (exp) {
  1292. let exps = [];
  1293. //获得行引用
  1294. let fArr = this.getFArr(exp);
  1295. for (let i = 0, len = fArr.length; i < len; i++) {
  1296. let r = this.getXNum([fArr[i]]);
  1297. if (r.length === 1) {
  1298. let node = cbTools.getBillByRow(calcBase.project.mainTree.items, r[0] - 1);
  1299. if (cbTools.isUnDef(node)) {
  1300. //continue;
  1301. calcBase.errMsg = "行引用错误";
  1302. throw "行引用错误";
  1303. }
  1304. exps.push({
  1305. orgExp: fArr[i],
  1306. newExp: "@" + node.data.ID,
  1307. });
  1308. } else {
  1309. calcBase.errMsg = "行引用错误";
  1310. throw "行引用错误";
  1311. }
  1312. }
  1313. for (let i = 0, len = exps.length; i < len; i++) {
  1314. exp = exp.replace(new RegExp(`${exps[i].orgExp}\\b`, "g"), exps[i].newExp);
  1315. }
  1316. return exp;
  1317. },
  1318. //将ID引用转换成行引用
  1319. toFExpr: function (exp, items) {
  1320. let nodeItems = items ? items : calcBase.project.mainTree.items;
  1321. let exps = [];
  1322. //获得ID引用
  1323. let fidArr = this.getFIDArr(exp);
  1324. for (let i = 0, len = fidArr.length; i < len; i++) {
  1325. let id = this.getUID([fidArr[i]]);
  1326. if (id.length === 1) {
  1327. let row = cbTools.getRowByID(nodeItems, id[0]);
  1328. if (cbTools.isUnDef(row)) {
  1329. continue;
  1330. }
  1331. exps.push({
  1332. orgExp: fidArr[i],
  1333. newExp: "F" + row,
  1334. });
  1335. }
  1336. }
  1337. for (let i = 0, len = exps.length; i < len; i++) {
  1338. exp = exp.replace(new RegExp(`${exps[i].orgExp}\\b`, "g"), exps[i].newExp);
  1339. }
  1340. return exp;
  1341. },
  1342. //将表达式转换为可编译的表达式
  1343. toCompileExpr: function (v) {
  1344. if (v === "") {
  1345. return "$CBC.base('NONE')";
  1346. }
  1347. //基数
  1348. let strs = _.uniq(this.getFigure(v));
  1349. let exps = [];
  1350. for (let i = 0, len = strs.length; i < len; i++) {
  1351. let exp = Object.create(null);
  1352. exp.orgExp = `{${strs[i]}}`;
  1353. exps.push(exp);
  1354. }
  1355. for (let i = 0, len = exps.length; i < len; i++) {
  1356. exps[i].compileExp = "$CBC.base('" + exps[i].orgExp + "')";
  1357. let regStr = exps[i].orgExp.replace(/\(/g, "\\(");
  1358. regStr = regStr.replace(/\)/g, "\\)");
  1359. regStr = regStr.replace(/\*/g, "\\*");
  1360. v = v.replace(new RegExp(regStr, "g"), exps[i].compileExp);
  1361. }
  1362. //去{}
  1363. v = v.replace(/[{, },]/g, "");
  1364. //行引用
  1365. let fidArr = _.uniq(this.getFIDArr(v));
  1366. let fExps = [];
  1367. for (let i = 0, len = fidArr.length; i < len; i++) {
  1368. let fExp = Object.create(null);
  1369. fExp.orgExp = fidArr[i];
  1370. fExps.push(fExp);
  1371. }
  1372. for (let i = 0, len = fExps.length; i < len; i++) {
  1373. fExps[i].compileExp = "$CBC.ref('" + fExps[i].orgExp + "')";
  1374. v = v.replace(new RegExp(fExps[i].orgExp, "g"), fExps[i].compileExp);
  1375. }
  1376. return v;
  1377. },
  1378. };
  1379. let cbCalctor = {
  1380. //计算基数
  1381. base: function (figure) {
  1382. if (figure === "NONE") {
  1383. return 0;
  1384. }
  1385. if (calcBase.project.property.valuationType === commonConstants.ValuationType.BOQ) {
  1386. // 工程量清单
  1387. return baseFigureTemplate.boq[calcBase.baseFigures[figure]["base"]]();
  1388. } else {
  1389. return baseFigureTemplate.budget[calcBase.baseFigures[figure]["base"]]();
  1390. }
  1391. },
  1392. //调价后计算基数
  1393. tenderBase: function (figure) {
  1394. if (figure === "NONE") {
  1395. return 0;
  1396. }
  1397. if (calcBase.project.property.valuationType === commonConstants.ValuationType.BOQ) {
  1398. // 工程量清单
  1399. return baseFigureTemplate.boq[calcBase.baseFigures[figure]["base"]](true);
  1400. } else {
  1401. return baseFigureTemplate.budget[calcBase.baseFigures[figure]["base"]](true);
  1402. }
  1403. },
  1404. //ID引用
  1405. ref: function (fExp) {
  1406. let ID = cbParser.getUID([fExp]);
  1407. if (ID.length === 1) {
  1408. let node = cbTools.getNodeByID(ID[0]);
  1409. return cbTools.isDef(node) &&
  1410. cbTools.isDef(node.data.feesIndex) &&
  1411. cbTools.isDef(node.data.feesIndex.common) &&
  1412. cbTools.isDef(node.data.feesIndex.common.totalFee)
  1413. ? node.data.feesIndex.common.totalFee
  1414. : 0;
  1415. }
  1416. return 0;
  1417. },
  1418. tenderRef: function (fExp) {
  1419. let ID = cbParser.getUID([fExp]);
  1420. if (ID.length === 1) {
  1421. let node = cbTools.getNodeByID(ID[0]);
  1422. return cbTools.isDef(node) &&
  1423. cbTools.isDef(node.data.feesIndex) &&
  1424. cbTools.isDef(node.data.feesIndex.common) &&
  1425. cbTools.isDef(node.data.feesIndex.common.tenderTotalFee)
  1426. ? node.data.feesIndex.common.tenderTotalFee
  1427. : 0;
  1428. }
  1429. return 0;
  1430. },
  1431. };
  1432. let calcBase = {
  1433. // 累进基数中的基准值,报表需要使用这个中间数据,因此需要入库处理,这里作为暂存
  1434. baseProgressiveFee: 0,
  1435. //正在执行计算的节点
  1436. activeNode: null,
  1437. errMsg: "表达式不正确",
  1438. success: false,
  1439. //清单固定行
  1440. fixedFlag: null,
  1441. fixedBills: Object.create(null),
  1442. //清单基数
  1443. baseFigures: Object.create(null),
  1444. //清单固定行可用基数对应 {flag: Number, baseList: Array}
  1445. flagValidBase: Object.create(null),
  1446. //清单可选基数映射,分两类:组织措施项目:排除父项和计算的父项; 其他项目、规费、税金、工程造价,及新增部分:显示所有计算基数
  1447. baseFigureClass: Object.create(null),
  1448. //初始化
  1449. init: function (project) {
  1450. let me = this;
  1451. me.project = project;
  1452. me.fixedFlag = fixedFlag;
  1453. cbTools.setFixedBills(project, me.fixedBills, me.fixedFlag);
  1454. if (project.property.valuationType === commonConstants.ValuationType.BOQ) {
  1455. me.baseFigures = baseFigureMap.boq;
  1456. } else {
  1457. me.baseFigures = baseFigureMap.budget;
  1458. }
  1459. cbTools.setBaseBills(me.baseFigures, me.fixedBills);
  1460. //设置清单固定行可用基数映射
  1461. cbTools.setValidBaseMapping(me.baseFigures, me.flagValidBase);
  1462. },
  1463. getBase: function (figure) {
  1464. return cbCalctor.base(figure);
  1465. },
  1466. getBaseByClass: function (node) {
  1467. return cbTools.getValidFigures(node);
  1468. },
  1469. calculate: function (node, reCalc = null) {
  1470. let me = calcBase,
  1471. $CBA = cbAnalyzer,
  1472. $CBP = cbParser,
  1473. $CBC = cbCalctor;
  1474. try {
  1475. me.activeNode = node;
  1476. me.success = false;
  1477. me.errMsg = "表达式不正确";
  1478. //分析输入式合法性
  1479. let exp = reCalc ? (cbTools.isDef(node.data.calcBase) ? node.data.calcBase : "") : $CBA.legalExp(node);
  1480. if (!cbTools.isDef(exp)) {
  1481. throw "表达式不正确";
  1482. }
  1483. //输入式转换表达式
  1484. let compileExp = $CBP.toCompileExpr(exp);
  1485. //计算
  1486. let calcExp = $CBP.percentToNum(compileExp);
  1487. let calcBaseValue = eval(calcExp);
  1488. if (!cbTools.isNum(calcBaseValue)) {
  1489. throw "基数计算结果不为数值";
  1490. }
  1491. //调价
  1492. let tenderCalcExp = calcExp.replace(new RegExp("base", "g"), "tenderBase").replace(new RegExp("ref", "g"), "tenderRef");
  1493. let tenderCalcBaseValue = eval(tenderCalcExp);
  1494. if (!cbTools.isNum(tenderCalcBaseValue)) {
  1495. throw "调价基数计算结果不为数值";
  1496. }
  1497. //存储
  1498. me.success = true;
  1499. node.updateData.calcBase = exp;
  1500. node.updateData.calcBaseValue = parseFloat(calcBaseValue).toDecimal(decimalObj.decimal("totalPrice", node));
  1501. node.updateData.tenderCalcBaseValue = parseFloat(tenderCalcBaseValue).toDecimal(decimalObj.decimal("totalPrice", node));
  1502. // progression来自overwrite里配置的全局变量
  1503. if (typeof progression !== "undefined" && calculateUtil.isProgressive(exp, progression)) {
  1504. node.updateData.baseProgressiveFee = me.baseProgressiveFee;
  1505. }
  1506. node.changed = true;
  1507. } catch (err) {
  1508. console.log(err);
  1509. if (typeof err === "object") {
  1510. err = "表达式不正确";
  1511. }
  1512. if (node) {
  1513. err = `第${node.serialNo() + 1}行${err}`;
  1514. }
  1515. alert(err);
  1516. }
  1517. },
  1518. };