Просмотр исходного кода

fix: 山东接口代码提交冲突导致的部分代码丢失

vian 2 лет назад
Родитель
Сommit
2c46760d60
1 измененных файлов с 292 добавлено и 61 удалено
  1. 292 61
      web/building_saas/standard_interface/export/shandong_common.js

+ 292 - 61
web/building_saas/standard_interface/export/shandong_common.js

@@ -107,39 +107,47 @@ INTERFACE_EXPORT = (() => {
   }
 
   const sectionNameMap = {
-    "清单 第100章 总则": true,
-    "清单 第200章 路基": true,
-    "清单 第300章 路面": true,
-    "清单 第400章 桥梁、涵洞": true,
-    "清单 第500章 隧道": true,
-    "清单 第600章 安全设施及预埋管线": true,
-    "清单 第700章 绿化及环境保护设施": true,
+    "清单第100章总则": true,
+    "清单第200章路基": true,
+    "清单第300章路面": true,
+    "清单第400章桥梁、涵洞": true,
+    "清单第500章隧道": true,
+    "清单第600章安全设施及预埋管线": true,
+    "清单第700章绿化及环境保护设施": true,
     // "清单 第800章 机电工程": true,
     // "清单 第900章 附属区房建工程":true
   }
 
   const ListCodeMap = {
     "第100章至700章清单": "1",
-    "清单 第100章 总则": "一",
-    "清单 第200章 路基": "二",
-    "清单 第300章 路面": "三",
-    "清单 第400章 桥梁、涵洞": "四",
-    "清单 第500章 隧道": "五",
-    "清单 第600章 安全设施及预埋管线": "六",
-    "清单 第700章 绿化及环境保护设施": "七",
+    // "清单 第100章 总则": "一",
+    // "清单 第200章 路基": "二",
+    // "清单 第300章 路面": "三",
+    // "清单 第400章 桥梁、涵洞": "四",
+    // "清单 第500章 隧道": "五",
+    // "清单 第600章 安全设施及预埋管线": "六",
+    // "清单 第700章 绿化及环境保护设施": "七",
     // "清单 第800章 机电工程": "八",
     // "清单 第900章 附属区房建工程": "九",
-    "已包含在清单合计中的材料、工程设备、专业工程暂估价合计": "10",
-    "清单合计减去材料、工程设备、专业工程暂估价合计": "11",
-    "计日工合计": "12",
-    "劳务": "12.1",
-    "材料": "12.2",
-    "机械": "12.3",
-    "暂列金额(不含计日工总额)": "13",
-    "投标报价": "14"
+    "清单第100章总则": "100",
+    "清单第200章路基": "200",
+    "清单第300章路面": "300",
+    "清单第400章桥梁、涵洞": "400",
+    "清单第500章隧道": "500",
+    "清单第600章安全设施及预埋管线": "600",
+    "清单第700章绿化及环境保护设施": "700",
+
+
+    "已包含在清单合计中的材料、工程设备、专业工程暂估价合计": "13",
+    "清单合计减去材料、工程设备、专业工程暂估价合计": "14",
+    "计日工合计": "15",
+    "劳务": "15.1",
+    "材料": "15.2",
+    "机械": "15.3",
+    "暂列金额(不含计日工总额)": "16",
+    "投标报价": "17"
   }
 
-
   const ratioCodeMap = {
     "01ZJF": "0",
     "02JXF": "1",
@@ -147,6 +155,12 @@ INTERFACE_EXPORT = (() => {
     "04ACFZF": "3"
   }
 
+  const reg1 = new RegExp('\n', 'g'), reg2 = new RegExp('\r', 'g')
+    , reg3 = new RegExp(' ', 'g'), reg4 = new RegExp('\t', 'g')
+    , reg5 = new RegExp('(', 'g'), reg6 = new RegExp(')', 'g')
+    , regRt1 = new RegExp('\n\r', 'g'), regRt2 = new RegExp('\r\n', 'g')
+    ;
+
   function getBasePrice(projectGLJID, tenderProject) {
     let glj = _.find(tenderProject.projectGLJ.datas.gljList, {
       id: projectGLJID
@@ -165,7 +179,41 @@ INTERFACE_EXPORT = (() => {
       })
       if (item) rate = item.feeRate;
     }
-    return rate
+    return rate;
+  }
+
+  function _billStrFilter(billStr) {
+    let rst = billStr;
+    if (typeof billStr === 'string') {
+      rst = billStr.replace(reg1, '').replace(reg2, '').replace(reg3, '').replace(reg4, '').replace(reg5, '(').replace(reg6, ')');
+    }
+    return rst;
+  }
+
+  function _chkAdhocChapterBillCode(billStr) {
+    let rst = false;
+    rst = (typeof billStr === 'string' &&
+      (billStr.indexOf('800章') >= 0 || billStr.indexOf('900章') >= 0 || billStr.indexOf('1000章') >= 0 || billStr.indexOf('1100章') >= 0 || billStr.indexOf('1200章') >= 0)
+    )
+    return rst;
+  }
+
+  function _extractAdhocChapter(billStr) {
+    let rst = '';
+    if (typeof billStr === 'string') {
+      if (billStr.indexOf('800章') >= 0) {
+        rst = '800';
+      } else if (billStr.indexOf('900章') >= 0) {
+        rst = '900';
+      } else if (billStr.indexOf('1000章') >= 0) {
+        rst = '1000';
+      } else if (billStr.indexOf('1100章') >= 0) {
+        rst = '1100';
+      } else if (billStr.indexOf('1200章') >= 0) {
+        rst = '1200';
+      }
+    }
+    return rst;
   }
 
   function billNameChecking(bNode, projectName, fixedFlag) {
@@ -203,14 +251,17 @@ INTERFACE_EXPORT = (() => {
           pass = data.name == "投标报价";
           break;
         case fixedFlag.ONE_HUNDRED_BILLS:
-          pass = data.name == "清单 第100章 总则";
+          // pass = data.name == "清单 第100章 总则";
+          pass = _billStrFilter(data.name) == "清单第100章总则";
           break;
       }
     } else {
       if (bNode.parent) {
         const pdata = bNode.parent.data;
         if (pdata.flagsIndex && pdata.flagsIndex.fixed && pdata.flagsIndex.fixed.flag == fixedFlag.ONE_SEVEN_BILLS) {
-          if (!sectionNameMap[data.name]) pass = false
+          if (!sectionNameMap[_billStrFilter(data.name)]) {
+            pass = _chkAdhocChapterBillCode(data.name);
+          }
         }
       }
     }
@@ -253,9 +304,6 @@ INTERFACE_EXPORT = (() => {
     const isBidSubmission = exportKind === BID_SUBMISSION; // 是否是投标
     const isControl = exportKind === CONTROL; // 是否是控制价
 
-    // 当前单位工程数据
-    let curTenderData = null;
-
     function emptyElement(name) {
       this.name = name;
       this.attrs = [];
@@ -903,7 +951,8 @@ INTERFACE_EXPORT = (() => {
       this.children.push(new SummaryOfCost(totalItem, proItem, safeItem, oneToSevenItem, feature));
       this.children.push(new MakeInfo(tenderProject));
       this.children.push(new Params(tenderProject));
-      this.children.push(new getBillsItems(tenderProject));
+      const cacheForFormula = _preCodeingForBills(tenderProject);
+      this.children.push(new getBillsItems(tenderProject, cacheForFormula));
       this.children.push(new getIndexs(tenderProject));
       let bidEvaluationMainMaterials = getBidEvaluationMainMaterial(tenderProject);
       if (bidEvaluationMainMaterials.length > 0) this.children.push(...bidEvaluationMainMaterials);
@@ -991,6 +1040,17 @@ INTERFACE_EXPORT = (() => {
       return rst;
     }
 
+    function _getFixedSum(tenderProject) {
+      let rst = 0;
+      tenderProject.Bills.datas.forEach((bill) => {
+        if (bill.specialProvisional == "固定费用") {
+          let bVal = _getFee(bill);
+          rst += bVal;
+        }
+      });
+      return rst;
+    }
+
     function quoteSummary(tenderProject) {
       let quoteSummaryItem = new emptyElement('QuoteSummary');
       // let attrs = [];
@@ -1003,6 +1063,7 @@ INTERFACE_EXPORT = (() => {
       // 1.6 投标报价 标记:9
       let topNode100To700, nodeZXZDJ, nodeQDKCZXZDJ, nodeJRG, nodeZLJE, nodeTBBJ;
       let chapterNodes = [];
+      let fixedSum = _getFixedSum(tenderProject); //山东有固定费用,此费用不参与到此项中去
       tenderProject.Bills.datas.forEach((bill) => {
         if (bill.flags && bill.flags.length > 0) {
           for (let flag of bill.flags) {
@@ -1059,7 +1120,8 @@ INTERFACE_EXPORT = (() => {
         nodeAttrs.push({ ItemNo: order, ChapterNo: '', Name: '第100章至700章清单合计', Sum: _getFee(topNode100To700) });
         order++;
         if (nodeZXZDJ) {
-          nodeAttrs.push({ ItemNo: order, ChapterNo: '', Name: '已包含在清单合计中的材料、工程设备、专业工程暂估价合计', Sum: _getFee(nodeZXZDJ) });
+          // nodeAttrs.push({ItemNo: order, ChapterNo: '', Name: '已包含在清单合计中的材料、工程设备、专业工程暂估价合计', Sum: _getFee(nodeZXZDJ) - fixedSum});
+          nodeAttrs.push({ ItemNo: order, ChapterNo: '', Name: '已包含在清单合计中的材料、工程设备、专业工程暂估价合计', Sum: _getFee(nodeZXZDJ) }); // 又不需要fixedSum了
           order++;
         }
         if (nodeQDKCZXZDJ) {
@@ -1302,11 +1364,20 @@ INTERFACE_EXPORT = (() => {
         items.forEach((glj) => {
           let mEstItemNode = new emptyElement('Item');
           mEstNode.children.push(mEstItemNode);
+          let gljName = glj.name;
+          if (tenderProject.evaluate_list.datas && tenderProject.evaluate_list.datas.length > 0) {
+            for (let relGlj of tenderProject.evaluate_list.datas) {
+              if (relGlj.projectGLJID == glj.id) {
+                gljName = relGlj.name;
+                break;
+              }
+            }
+          }
           let attrs = [
             { name: 'ItemNo', value: itemNo },
             { name: 'Code', value: _getBidGljCode(tenderProject, glj) },
             { name: 'Number', value: glj.code },
-            { name: 'Name', value: glj.name },
+            { name: 'Name', value: gljName },
             { name: 'Unit', value: glj.unit },
             { name: 'Num', value: glj.tenderQuantity },
             // {name: 'Price', value: _getNumValueByExportKind(glj.unit_price.market_price)},
@@ -1410,12 +1481,19 @@ INTERFACE_EXPORT = (() => {
           mEstNode.children.push(mEstItemNode);
           let ttl = _getFee(bill);
           sum += ttl;
+          let jobContent = '';
+          if (bill.jobContent && bill.jobContent.length > 0) {
+            jobContent = bill.jobContent.toString();
+          } else {
+            jobContent = (bill.jobContentText) ? bill.jobContentText : '';
+          }
+          jobContent = jobContent.replace(regRt1, '
').replace(regRt2, '
').replace(reg1, '
').replace(reg2, '
'); // 转成XML的换行转义符
           let attrs = [
             { name: 'ItemNo', value: sno + 1 },
             { name: 'Code', value: bill.code },
             { name: 'Number', value: bill.code },
             { name: 'Name', value: bill.name },
-            { name: 'Content', value: bill.jobContent.toString() },
+            { name: 'Content', value: jobContent },
             // {name: 'Sum', value: _getNumValueByExportKind(scMathUtil.roundForObj(ttl, 0)), type:TYPE.DECIMAL},
             { name: 'Sum', value: ttl, type: TYPE.DECIMAL },
             // {name: 'Sum', value: 0, type:TYPE.DECIMAL},
@@ -1761,7 +1839,7 @@ INTERFACE_EXPORT = (() => {
     }
 
 
-    function getBillsItems(tenderProject) {
+    function getBillsItems(tenderProject, cacheForFormula) {
       let items = new emptyElement("Items");
       let rootNodes = tenderProject.mainTree.roots;
       for (let r of rootNodes) {
@@ -1772,6 +1850,10 @@ INTERFACE_EXPORT = (() => {
 
       function setItem(bNode, level, list) {
         if (bNode.sourceType == ModuleNames.ration) return;
+        // 判断: 1. 招标清单 2. 是否量价,都是的话,return
+        if (isBidInvitation && (bNode.data.specialProvisional == "材料暂估" || bNode.data.specialProvisional == "工程设备")) {
+          return;
+        }
         let item = new bill(bNode, level);
         if (bNode.children && bNode.children.length > 0) {
           level += 1;
@@ -1822,6 +1904,7 @@ INTERFACE_EXPORT = (() => {
         function bill(bNode, level) {
           let data = bNode.data;
           let CostKind = 3;
+          if (data.name === undefined || data.name === null) data.name = '';
           if (data.name && data.name.indexOf("安全生产费") != -1) CostKind = 1;
           if (data.name && data.name.indexOf("暂列金额") != -1) CostKind = 2;
           //1 = 工程量×综合单价;2 = 计算基数×费率;3 = 工程量×单价。
@@ -1831,6 +1914,7 @@ INTERFACE_EXPORT = (() => {
           if (data.specialProvisional == "材料暂估") ProvisionalType = 0;
           if (data.specialProvisional == "工程设备") ProvisionalType = 1;
           if (data.specialProvisional == "专业工程") ProvisionalType = 2;
+          if (data.specialProvisional == "固定费用") ProvisionalType = 3;
 
           //MpRatio
           let MpRatio = "";
@@ -1844,8 +1928,14 @@ INTERFACE_EXPORT = (() => {
           let fail = billNameChecking(bNode, tenderProject.projectInfo.name, fixedFlag)
           //fail: { hint: '错误提示', type: '提示所属(基本就是单位工程名称)' }
           let ListCode = "";
-          if (ListCodeMap[data.name]) ListCode = ListCodeMap[data.name];
-          if (data.code && data.code != "") ListCode = data.code;
+          // if (ListCodeMap[data.name]) ListCode = ListCodeMap[data.name];
+          if (ListCodeMap[_billStrFilter(data.name)]) {
+            ListCode = ListCodeMap[_billStrFilter(data.name)];
+          } else if (_chkAdhocChapterBillCode(data.name)) {
+            ListCode = _extractAdhocChapter(data.name);
+          } else if (data.code && data.code != "") {
+            ListCode = data.code;
+          }
 
           let qtyFormula = data.feesIndex && data.feesIndex.common ? data.feesIndex.common.tenderTotalFee : "";
           //data.calcBase //data.calcBase ? cbParser.toFExpr(data.calcBase, tenderProject.mainTree.items) : "",
@@ -1863,6 +1953,11 @@ INTERFACE_EXPORT = (() => {
             //判断公式(calcBase)是否为正常的计算公式(即非直接输入数量),
           }
 
+          let formulaCode = '';
+          if (cacheForFormula['_' + data.ID] && cacheForFormula['_' + data.ID].formulaCode) {
+            formulaCode = cacheForFormula['_' + data.ID].formulaCode;
+          }
+
           const attrs = [{
             name: "ListCode",
             value: ListCode,
@@ -1957,19 +2052,24 @@ INTERFACE_EXPORT = (() => {
             name: "ItemType",
             value: getItemType(bNode),
           },
-            /* {
-              name: "FomulaCode",
-              value: ""
-            }, */
+          /* {
+            name: "FomulaCode",
+            value: ""
+          }, */
+          {
+            name: "FormulaCode",
+            value: formulaCode,
+          },
           ];
           //投标、招标控制价时。取单价。
           //招标时,如果是“安全生产费”或“暂列金额”,取单价,否则取0。
-          if (isBidSubmission || isControl || CostKind == 1 || CostKind == 2 || ProvisionalType === 2) {
+          if (isBidSubmission || isControl || CostKind == 1 || CostKind == 2 || ProvisionalType === 2 || ProvisionalType === 3) {
             attrs[5].value = data.feesIndex && data.feesIndex.common ? scMathUtil.roundForObj(data.feesIndex.common.tenderUnitFee, tenderProject.property.decimal.bills.unitPrice) : "";
             attrs[7].value = data.feesIndex && data.feesIndex.common ? scMathUtil.roundForObj(data.feesIndex.common.tenderTotalFee, tenderProject.property.decimal.bills.totalPrice) : "";
             //暂列金额 数量为0的时候,单价输出0
             if (CostKind == 2 && !gljUtil.isNotEmpty(data.quantity)) attrs[5].value = 0
           }
+          let fixedSumVal = _getFixedSum(tenderProject); // 固定费用
 
           Element.call(this, "Item", attrs);
           let cc = CostComposition(bNode);
@@ -1983,29 +2083,16 @@ INTERFACE_EXPORT = (() => {
             // 当清单有清单基数和费率,那么应该就是没有定额,不输出定额;
             // 清单没有基数和费率,也没有下挂定额,那么也不输出定额相关字段;
             // 清单有下挂定额、量价,那么输出定额相关数据。
-            if (isBidInvitation) return null;
-            // let bSet = true;
-            // if (bNode.data.hasOwnProperty('calcBase')) {
-            //   let chkNaN = parseFloat(bNode.data.calcBase);
-            //   if (!isNaN(chkNaN)) {
-            //     bSet = false;
-            //   }
-            // } else {
-            //   bSet = false;
-            // }
-            // if (!bSet) return null;
-            // 1. 如果是招标清单,不输出定额
-            // 2. 其他情况,如果清单下有定额,就输出定额
-            // 上面写了一堆的废话,TNND,不就2句话解释的事情,非得扯基数判断
+            // if (isBidInvitation) return null; // 山东接口又要这个了
             let CostComposition = new emptyElement('CostComposition');
             let Norms = [];
             let Costs = [];
             if (bNode.children && bNode.children.length > 0 && bNode.children[0].sourceType == ModuleNames.ration) {
               for (let r of bNode.children) {
                 if (r.data.type == rationType.ration) {
-                  if (isEmptyRation(r.data)) continue;//定额空行不输出到接口文件中。
+                  if (isEmptyRation(r.data) || isBidInvitation) continue; // 招标 或者 定额空行不输出到接口文件中。
                   Norms.push(new Ration(r.data));
-                } else {
+                } else if (!isBidInvitation) {
                   Costs.push(new Cost(r.data));
                 }
               }
@@ -2022,13 +2109,14 @@ INTERFACE_EXPORT = (() => {
 
 
             function Formula(bills) {
+              let sumFix = (bills.name === '已包含在清单合计中的材料、工程设备、专业工程暂估价合计') ? fixedSumVal : 0;
               const attrs = [{
                 name: "Name",
                 value: bills.name
               },
               {
                 name: "Formulas",
-                value: bills.calcBase
+                value: _getFormulaDispName(cacheForFormula, bills)
               },
               {
                 name: "Ratio",
@@ -2037,7 +2125,8 @@ INTERFACE_EXPORT = (() => {
               {
                 name: "Sum",
                 // value: bills.feesIndex && bills.feesIndex.common ? bills.feesIndex.common.tenderTotalFee : "",
-                value: _getNumValueByExportKind(bills.feesIndex && bills.feesIndex.common ? bills.feesIndex.common.tenderTotalFee : ""),
+                // value: _getNumValueByExportKind(bills.feesIndex && bills.feesIndex.common ? bills.feesIndex.common.tenderTotalFee : "") - sumFix,
+                value: _getNumValueByExportKind(bills.feesIndex && bills.feesIndex.common ? bills.feesIndex.common.tenderTotalFee : ""), // 不用再减一次sumFix
                 type: TYPE.DECIMAL
               },
               {
@@ -2207,7 +2296,12 @@ INTERFACE_EXPORT = (() => {
                 name: 'Sum',
                 value: 0 //fee.tenderTotalFee
               }]
-              if ((isBidSubmission || isControl) && item.feesIndex && item.feesIndex[type]) attrs[1].value = scMathUtil.roundForObj(item.feesIndex[type].tenderTotalFee, decimalNum);
+              if ((isBidSubmission || isControl) && item.feesIndex && item.feesIndex[type]) {
+                attrs[1].value = scMathUtil.roundForObj(item.feesIndex[type].tenderTotalFee, decimalNum);
+                if ((item.name === '已包含在清单合计中的材料、工程设备、专业工程暂估价合计') && (itemFeeMap[type] === 'JAF')) {
+                  attrs[1].value = scMathUtil.roundForObj(attrs[1].value - fixedSumVal, decimalNum);
+                }
+              }
               Element.call(this, "CostItem", attrs);
             }
             return CostStructure;
@@ -2502,7 +2596,6 @@ INTERFACE_EXPORT = (() => {
     let EprjInfos = [];
     for (let c of projectData.children) {
       let tenderProject = tenderDetailMap[c.ID];
-      curTenderData = tenderProject;
       let feeRataDatas = tenderProject.FeeRate.datas;
       Rates.push(new Rate(tenderProject, feeRataDatas, seriNo));
       Practs.push(new Pract(tenderProject, seriNo));
@@ -2529,6 +2622,144 @@ INTERFACE_EXPORT = (() => {
     return hashHex.toUpperCase();
   }
 
+  function _extractBillCalcRefs(currentBill) {
+    const rst = [];
+    function _extract(spliter, excluded = true, nextGap) {
+      let currentBillCalcBase = currentBill.calcBase;
+      let currentIdx = currentBillCalcBase.indexOf(spliter);
+      let exCnt = 0;
+      if (excluded) exCnt = spliter.length;
+      while (currentIdx >= 0) {
+        let bId = currentBillCalcBase.substr(currentIdx + excluded, nextGap);
+        if (!rst.includes(bId)) {
+          rst.push(bId);
+        }
+        currentBillCalcBase = currentBillCalcBase.substr(currentIdx + excluded + nextGap);
+        currentIdx = currentBillCalcBase.indexOf(spliter);
+      }
+    }
+    if (typeof currentBill.calcBase === 'string') {
+      //1. 抽取@引用
+      _extract('@', true, 36);
+      //2. 抽取特殊引用
+      // 2.1 {各章清单合计}
+      _extract('{各章清单合计}', false, '{各章清单合计}'.length);
+      // 2.2 {100章以外清单合计}
+      _extract('{100章以外清单合计}', false, '{100章以外清单合计}'.length);
+    }
+    return rst;
+  }
+
+  function _preCodeingForBills(tenderProject) {
+    const cacheObj = {};
+    function _chkAdhocChapterBill(bill) {
+      let rst = false;
+      if (typeof bill.name === 'string' && bill.name.includes('00章') && bill.name.includes('清单')) {
+        rst = true;
+      }
+      return rst;
+    }
+
+    function _setCache(bNode) {
+      cacheObj['_' + bNode.data.ID] = bNode.data;
+      if (bNode.children && bNode.children.length > 0) {
+        for (let subNode of bNode.children) {
+          _setCache(subNode);
+        }
+      }
+    }
+    let rootNodes = tenderProject.mainTree.roots;
+    for (let rootNode of rootNodes) {
+      _setCache(rootNode);
+    }
+
+    let cnt = 1;
+    let billsForAcc = [];
+    for (let bill of tenderProject.Bills.datas) {
+      //这一步设置特殊清单(各章清单合计, 100章~1200章)
+      cacheObj['_{100章以外清单合计}'] = {};
+      if (_billStrFilter(bill.name).includes('第100章至700章清单') || sectionNameMap[_billStrFilter(bill.name)] || _chkAdhocChapterBill(bill)) {
+        if (cacheObj['_' + bill.ID]) {
+          if (!cacheObj['_' + bill.ID].hasOwnProperty('formulaCode')) {
+            cacheObj['_' + bill.ID].formulaCode = `F${cnt}`;
+            cnt++;
+          }
+        }
+        if (_billStrFilter(bill.name).includes('第100章至700章清单')) {
+          cacheObj['_{各章清单合计}'] = {};
+          cacheObj['_{各章清单合计}'].formulaCode = `{F${cnt - 1}}`;
+        } else if (!_billStrFilter(bill.name).includes('清单第100章')) {
+          billsForAcc.push(`F${cnt - 1}`);
+        }
+      }
+    }
+    let tmpStr = ''
+    for (let idx = 0; idx < billsForAcc.length; idx++) {
+      if (idx === 0) {
+        tmpStr = '( ' + `{${billsForAcc[idx]}}`;
+      } else {
+        tmpStr = tmpStr + ` + {${billsForAcc[idx]}}`;
+      }
+      if (idx === billsForAcc.length - 1) tmpStr = tmpStr + ' )';
+    }
+    cacheObj['_{100章以外清单合计}'].formulaCode = tmpStr;
+
+    for (let bill of tenderProject.Bills.datas) {
+      let billRefs = _extractBillCalcRefs(bill);
+      for (let refBillId of billRefs) {
+        if (cacheObj['_' + refBillId]) {
+          if (!cacheObj['_' + refBillId].hasOwnProperty('formulaCode')) {
+            cacheObj['_' + refBillId].formulaCode = `F${cnt}`;
+            cnt++;
+          }
+        }
+      }
+    }
+    return cacheObj;
+  }
+
+  function _getFormulaDispName(cacheForFormula, currentBill) {
+    let rst = currentBill.calcBase;
+    if (typeof currentBill.calcBase === 'string') {
+      //1. @引用
+      let currentBillCalcBase = currentBill.calcBase;
+      let currentIdx = currentBillCalcBase.indexOf('@');
+      let bIdArr = [], replaceArr = [];
+      while (currentIdx >= 0) {
+        let bId = currentBillCalcBase.substr(currentIdx + 1, 36);
+        bIdArr.push(bId);
+        if (cacheForFormula['_' + bId]) {
+          if (cacheForFormula['_' + bId].hasOwnProperty('formulaCode')) {
+            replaceArr.push(`{${cacheForFormula['_' + bId].formulaCode}}`);
+          } else {
+            replaceArr.push(`{无formulaCode错误:${bId}}`);
+          }
+        } else {
+          replaceArr.push(`{引用错误:${bId}}`);
+        }
+        currentBillCalcBase = currentBillCalcBase.substr(currentIdx + 37);
+        currentIdx = currentBillCalcBase.indexOf('@');
+      }
+      let tempBillCalcBase = currentBill.calcBase;
+      for (let idx = 0; idx < bIdArr.length; idx++) {
+        tempBillCalcBase = tempBillCalcBase.replace('@' + bIdArr[idx], replaceArr[idx]);
+      }
+      //2. 特殊引用
+      //{各章清单合计} {100章以外清单合计}
+      if (tempBillCalcBase.includes('{各章清单合计}')) {
+        console.log(`特殊引用清单{各章清单合计}:${currentBill.name}(${currentBill.code} - ${tempBillCalcBase})`);
+        tempBillCalcBase = tempBillCalcBase.replace('{各章清单合计}', cacheForFormula['_{各章清单合计}'].formulaCode);
+      }
+      if (tempBillCalcBase.includes('{100章以外清单合计}')) {
+        console.log(`特殊引用清单{100章以外清单合计}:${currentBill.name}(${currentBill.code} - ${tempBillCalcBase})`);
+        tempBillCalcBase = tempBillCalcBase.replace('{100章以外清单合计}', cacheForFormula['_{100章以外清单合计}'].formulaCode);
+      }
+      // 
+      rst = tempBillCalcBase;
+    }
+    return rst;
+  }
+
   return {
     entry,
   };