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

Merge branch 'master' of http://192.168.1.41:3000/SmartCost/YangHuCost

Tony Kang 3 лет назад
Родитель
Сommit
b995b2bbdf

+ 1 - 1
Dockerfile

@@ -4,7 +4,7 @@ WORKDIR /home/ConstructionCost
 
 COPY package.json /home/ConstructionCost/
 
-RUN npm install
+RUN npm install --registry=https://registry.npmmirror.com
 
 FROM base-alpine-new-node:latest
 

+ 25 - 0
web/building_saas/main/html/main.html

@@ -1698,6 +1698,31 @@
         </div>
     </div>
 
+    <!--弹出 导入Excel预算价-->
+    <div class="modal fade" id="importPriceForm" data-backdrop="static">
+        <div class="modal-dialog" style="z-index: 800" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">导入Excel预算价</h5>
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                        <span aria-hidden="true">&times;</span>
+                    </button>
+                </div>
+                <div class="modal-body">
+                    <div class="custom-file">
+                        <input type="file" class="custom-file-input" id="customPriceFile" lang="zh" accept=".xlsx">
+                        <label class="custom-file-label" for="customPriceFile" style="white-space: nowrap; overflow: hidden;">请选择.xlsx文件</label>
+                    </div>
+                    <div class="alert alert-success mt-3" id="showAlert" role="alert" style="display: none;">提示</div>
+                </div>
+                <div class="modal-footer">
+                    <a href="javascript:void(0);" class="btn btn-primary" id="importPriceBtn">确定导入</a>
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                </div>
+            </div>
+        </div>
+    </div>
+
     <!--弹出 粘贴位置选择-->
     <div class="modal fade" id="pastePosition" data-backdrop="static">
         <div class="modal-dialog" role="document">

+ 2 - 2
web/building_saas/main/js/models/bills.js

@@ -182,7 +182,7 @@ var Bills = {
             insertData.forEach(function (data) {
                 if (data.type === idTree.updateType.new) {
                     data.data.type = billType.BILL;
-                    if (projectObj.project.property.valuationType === commonConstants.ValuationType.BOQ) {
+                    if ([commonConstants.ValuationType.BOQ, commonConstants.ValuationType.BILL_BUDGET].includes(projectObj.project.property.valuationType)) {
                         data.data.unitPriceAnalysis = 1;
                     }
                     newData = data.data;
@@ -200,7 +200,7 @@ var Bills = {
             var newData = null, that = this;
             insertData.forEach(function (data) {
                 if (data.type === idTree.updateType.new) {
-                    if (projectObj.project.property.valuationType === commonConstants.ValuationType.BOQ) {
+                    if ([commonConstants.ValuationType.BOQ, commonConstants.ValuationType.BILL_BUDGET].includes(projectObj.project.property.valuationType)) {
                         data.data.unitPriceAnalysis = 1;
                     }
                     data.data.code = that.newFormatCode(stdBillsData.code);

+ 7 - 6
web/building_saas/main/js/models/calc_base.js

@@ -1253,8 +1253,9 @@ let cbParser = {
   },
   //获取表达式中的中文式
   getCN: function (expr) {
-    //let cnRex = /\d*[\u4e00-\u9fa5]{1,}\({0,}[\u4e00-\u9fa5]{0,}\*?\d*%*、?[\u4e00-\u9fa5]{0,}\){0,}[\u4e00-\u9fa5]{0,}/g;
-    let cnRex = /\d*[\u4e00-\u9fa5]{1,}\({0,}[\u4e00-\u9fa5]{0,}\*?\d*%*、?[\u4e00-\u9fa5]{0,}\){0,}[\u4e00-\u9fa5]{0,}\(?[\u4e00-\u9fa5]{0,}\)?/g;
+    // let cnRex = /\d*[\u4e00-\u9fa5]{1,}\({0,}[\u4e00-\u9fa5]{0,}\*?\d*%*、?[\u4e00-\u9fa5]{0,}\){0,}[\u4e00-\u9fa5]{0,}\(?[\u4e00-\u9fa5]{0,}\)?/g;
+    // 支持{}内的:多个顿号、小括号、中文括号。
+    let cnRex = /\d*[\u4e00-\u9fa5]{1,}\({0,}([\u4e00-\u9fa5]{0,}\*?\d*%*、?)+[\u4e00-\u9fa5]{0,}\){0,}[\u4e00-\u9fa5]{0,}\(?[\u4e00-\u9fa5]{0,}\)?/g;
     return _.filter(expr.match(cnRex), function (data) {
       return data;
     });
@@ -1401,7 +1402,7 @@ let cbCalctor = {
     if (figure === "NONE") {
       return 0;
     }
-    if (calcBase.project.property.valuationType === commonConstants.ValuationType.BOQ) {
+    if ([commonConstants.ValuationType.BOQ, commonConstants.ValuationType.BILL_BUDGET].includes(calcBase.project.property.valuationType)) {
       // 工程量清单
       return baseFigureTemplate.boq[calcBase.baseFigures[figure]["base"]]();
     } else {
@@ -1413,8 +1414,8 @@ let cbCalctor = {
     if (figure === "NONE") {
       return 0;
     }
-    if (calcBase.project.property.valuationType === commonConstants.ValuationType.BOQ) {
-      // 工程量清单
+
+    if ([commonConstants.ValuationType.BOQ, commonConstants.ValuationType.BILL_BUDGET].includes(calcBase.project.property.valuationType)) {
       return baseFigureTemplate.boq[calcBase.baseFigures[figure]["base"]](true);
     } else {
       return baseFigureTemplate.budget[calcBase.baseFigures[figure]["base"]](true);
@@ -1471,7 +1472,7 @@ let calcBase = {
     me.project = project;
     me.fixedFlag = fixedFlag;
     cbTools.setFixedBills(project, me.fixedBills, me.fixedFlag);
-    if (project.property.valuationType === commonConstants.ValuationType.BOQ) {
+    if ([commonConstants.ValuationType.BOQ, commonConstants.ValuationType.BILL_BUDGET].includes(project.property.valuationType)) {
       me.baseFigures = baseFigureMap.boq;
     } else {
       me.baseFigures = baseFigureMap.budget;

+ 366 - 356
web/building_saas/main/js/views/importBills.js

@@ -1,4 +1,4 @@
-'use strict';
+"use strict";
 
 /**
  *
@@ -9,387 +9,397 @@
  */
 
 /*
-* 清单导入模块,前端导入excel,进行数据提取,用lz-string进行压缩上传处理
-* */
+ * 清单导入模块,前端导入excel,进行数据提取,用lz-string进行压缩上传处理
+ * */
 
 const importBills = (function () {
-    //单元格数据是否存在
-    function _isDef(data) {
-        return typeof data !== 'undefined' && data !== null && data !== '';
-    }
+  //单元格数据是否存在
+  function _isDef(data) {
+    return typeof data !== "undefined" && data !== null && data !== "";
+  }
 
-    //去除转义字符
-    function _deESC(data) {
-        return _isDef(data) ? data.toString().replace(/[\r\n\s\t]/g, '') : data;
-    }
+  //去除转义字符
+  function _deESC(data) {
+    return _isDef(data) ? data.toString().replace(/[\r\n\s\t]/g, "") : data;
+  }
 
-    function _deNR(data) {
-        return _isDef(data) ? data.toString().replace(/[\r\n]/g, '') : data;
+  function _deNR(data) {
+    return _isDef(data) ? data.toString().replace(/[\r\n]/g, "") : data;
+  }
+  //find 返回最后匹配
+  function findLast(datas, func) {
+    let filter = datas.filter(func);
+    if (filter.length > 0) {
+      return filter[filter.length - 1];
     }
-    //find 返回最后匹配
-    function findLast(datas, func) {
-        let filter = datas.filter(func);
-        if (filter.length > 0) {
-            return filter[filter.length - 1];
-        }
-        return null;
+    return null;
+  }
+  const fileType = {
+    gcl: 0, //工程量清单
+    qdsl: 1, //清单示例
+    gclex: 2, // 单机版导出的工程量清单预算表,需要转换成清单示例表来处理
+  };
+  //获取列字段对应
+  function getColMapping(type) {
+    if (type === 0) {
+      //工程量清单
+      return { code: 0, name: 1, unit: 2, quantity: 4, unitPrice: 5 };
+    } else {
+      //清单示例表
+      return { code: 0, name: 1, unit: 2, quantity: 3, unitPrice: 4 };
     }
-    const fileType = {
-        gcl: 0, //工程量清单
-        qdsl: 1, //清单示例
-        gclex: 2, // 单机版导出的工程量清单预算表,需要转换成清单示例表来处理
-    };
-    //获取列字段对应
-    function getColMapping(type) {
-        if (type === 0) {   //工程量清单
-            return { code: 0, name: 1, unit: 2, quantity: 4, unitPrice: 5  };
-        } else {    //清单示例表
-            return { code: 0, name: 1, unit: 2, quantity: 3, unitPrice: 4 };
-        }
+  }
+  function isGCLHead(dataRow, nextDataRow) {
+    const cell = dataRow[0];
+    const nextCell = nextDataRow && nextDataRow[0];
+    return cell && cell.value === "工程量清单" && (!nextCell || !/建设项目名称/.test(nextCell.value)); // 兼容招清单01-1表
+  }
+  function isGCLExtendHead(dataRow, nextDataRow) {
+    const cell = dataRow[0];
+    const nextCell = nextDataRow && nextDataRow[0];
+    if ((cell && cell.value === "工程量清单预算表") || (nextCell && /建设项目名称/.test(nextCell.value))) {
+      // 兼容招清单01-1表
+      return true;
     }
-    function isGCLHead(dataRow, nextDataRow) {
-        const cell = dataRow[0];
-        const nextCell = nextDataRow && nextDataRow[0];
-        return cell && cell.value === '工程量清单' && (!nextCell || !/建设项目名称/.test(nextCell.value)); // 兼容招清单01-1表
+  }
+  //分析文件,1、工程量清单 2、清单示例表
+  function getFileType(sheetData) {
+    let dataTable = sheetData.data.dataTable,
+      // rowCount = sheetData.rowCount;
+      rowCount = sheetData.rows.length;
+    for (let row = 0; row < rowCount; row++) {
+      if (isGCLHead(dataTable[row], dataTable[row + 1])) {
+        return fileType.gcl;
+      }
+      if (isGCLExtendHead(dataTable[row], dataTable[row + 1])) {
+        return fileType.gclex;
+      }
     }
-    function isGCLExtendHead(dataRow, nextDataRow) {
-        const cell = dataRow[0];
-        const nextCell = nextDataRow && nextDataRow[0];
-        if ((cell && cell.value === '工程量清单预算表') || (nextCell && /建设项目名称/.test(nextCell.value))) { // 兼容招清单01-1表
-            return true;
+    return fileType.qdsl;
+  }
+  //提取工程量清单数据
+  //层级由depth确定,表格里最顶层depth为0(表头里一清单),表格内容里数据的depth为空格数+1
+  function extractGCLDatas(sheetData, colMapping) {
+    let dataTable = sheetData.data.dataTable,
+      // rowCount = sheetData.rowCount;
+      rowCount = sheetData.rows.length;
+    let rst = [];
+    for (let row = 0; row < rowCount; row++) {
+      //表格中顶层节点
+      if (isGCLHead(dataTable[row], dataTable[row + 1])) {
+        let rootRow = dataTable[row + 2];
+        let name = rootRow[0].value ? _deNR(rootRow[0].value) : "";
+        let existsRoot = findLast(rst, (x) => x.name === name && x.depth === 0);
+        if (!existsRoot) {
+          let root = {
+            ID: uuid.v1(),
+            NextSiblingID: -1,
+            ParentID: -1,
+            name: name,
+            depth: 0,
+            parent: null,
+            unitPriceAnalysis: 1,
+          };
+          let preData = findLast(rst, (x) => x.depth === root.depth);
+          if (preData) {
+            preData.NextSiblingID = root.ID;
+          }
+          rst.push(root);
         }
+        row += 3;
+        continue;
+      }
+      let code = dataTable[row][colMapping.code] ? dataTable[row][colMapping.code].value : null,
+        name = dataTable[row][colMapping.name] ? _deNR(dataTable[row][colMapping.name].value) : null,
+        unit = dataTable[row][colMapping.unit] ? dataTable[row][colMapping.unit].value : null,
+        quantity = dataTable[row][colMapping.quantity] ? dataTable[row][colMapping.quantity].value : null,
+        unitPrice = dataTable[row][colMapping.unitPrice] ? dataTable[row][colMapping.unitPrice].value : null;
+      if ((!code && !name) || /合计/.test(code)) {
+        //过滤掉同时没有编号和名称的、过滤合计行
+        continue;
+      }
+      // “子目号”、“单位”、“数量”都为空,“子目名称”不为空时,应将此行清单名称合并到上一行
+      let lastData = rst[rst.length - 1];
+      if (!code && !unit && !quantity && name) {
+        lastData.name += name;
+        continue;
+      }
+      //表格内的数据
+      code = String(code);
+      let depth = getDepth(code);
+      let data = {
+        ID: uuid.v1(),
+        NextSiblingID: -1,
+        ParentID: -1,
+        code: code,
+        name: name,
+        unit: unit,
+        quantity: quantity,
+        depth: depth,
+        unitPriceAnalysis: 1,
+      };
+      if (+unitPrice && +quantity) {
+        unitPrice = scMathUtil.roundForObj(unitPrice, decimalObj.bills.unitPrice);
+        const totalPrice = scMathUtil.roundForObj(unitPrice * +quantity, decimalObj.bills.totalPrice);
+        data.fees = [
+          {
+            fieldName: "common",
+            tenderTotalFee: totalPrice,
+            tenderUnitFee: unitPrice,
+            totalFee: totalPrice,
+            unitFee: unitPrice,
+          },
+        ];
+        data.calcFlag = treeNodeCalcFlag.customUnitPrice;
+      }
+      //获取data的父节点链,成为兄弟节点,只能在父链里找前兄弟(不能跨父链)
+      let parents = getParents(lastData);
+      let preData = findLast(parents, (x) => x.depth === depth);
+      if (preData) {
+        preData.NextSiblingID = data.ID;
+        data.ParentID = preData.ParentID;
+        data.parent = preData.parent;
+      } else {
+        data.ParentID = lastData.ID;
+        data.parent = lastData;
+      }
+      rst.push(data);
     }
-    //分析文件,1、工程量清单 2、清单示例表
-    function getFileType(sheetData) {
-        let dataTable = sheetData.data.dataTable,
-            // rowCount = sheetData.rowCount;
-            rowCount = sheetData.rows.length;
-        for (let row = 0; row < rowCount; row++) {
-            if (isGCLHead(dataTable[row], dataTable[row + 1])) {
-                return fileType.gcl;
-            }
-            if (isGCLExtendHead(dataTable[row], dataTable[row + 1])) {
-                return fileType.gclex;
-            }
-        }
-        return fileType.qdsl;
+    console.log(rst);
+    return rst;
+    function getDepth(code) {
+      if (!code) {
+        return 1;
+      }
+      let match = code.match(/\s/g);
+      return match ? match.length + 1 : 1;
     }
-    //提取工程量清单数据
-    //层级由depth确定,表格里最顶层depth为0(表头里一清单),表格内容里数据的depth为空格数+1
-    function extractGCLDatas(sheetData, colMapping) {
-        let dataTable = sheetData.data.dataTable,
-            // rowCount = sheetData.rowCount;
-            rowCount = sheetData.rows.length;
-        let rst = [];
-        for (let row = 0; row < rowCount; row++) {
-            //表格中顶层节点
-            if (isGCLHead(dataTable[row], dataTable[row + 1])) {
-                let rootRow = dataTable[row + 2];
-                let name = rootRow[0].value ? _deNR(rootRow[0].value) : '';
-                let existsRoot = findLast(rst, x => x.name === name && x.depth === 0);
-                if (!existsRoot) {
-                    let root = {
-                        ID: uuid.v1(),
-                        NextSiblingID: -1,
-                        ParentID: -1,
-                        name: name,
-                        depth: 0,
-                        parent: null,
-                        unitPriceAnalysis: 1
-                    };
-                    let preData = findLast(rst, x => x.depth === root.depth);
-                    if (preData) {
-                        preData.NextSiblingID = root.ID;
-                    }
-                    rst.push(root);
-                }
-                row += 3;
-                continue;
-            }
-            let code = dataTable[row][colMapping.code] ? dataTable[row][colMapping.code].value : null,
-                name = dataTable[row][colMapping.name] ? _deNR(dataTable[row][colMapping.name].value) : null,
-                unit = dataTable[row][colMapping.unit] ? dataTable[row][colMapping.unit].value : null,
-                quantity = dataTable[row][colMapping.quantity] ? dataTable[row][colMapping.quantity].value : null,
-                unitPrice = dataTable[row][colMapping.unitPrice] ? dataTable[row][colMapping.unitPrice].value : null;
-            if (!code && !name || /合计/.test(code)) {   //过滤掉同时没有编号和名称的、过滤合计行
-                continue;
-            }
-            // “子目号”、“单位”、“数量”都为空,“子目名称”不为空时,应将此行清单名称合并到上一行
-            let lastData = rst[rst.length - 1];
-            if (!code && !unit && !quantity && name) {
-                lastData.name += name;
-                continue;
-            }
-            //表格内的数据
-            code = String(code);
-            let depth = getDepth(code);
-            let data = {
-                ID: uuid.v1(),
-                NextSiblingID: -1,
-                ParentID: -1,
-                code: code,
-                name: name,
-                unit: unit,
-                quantity: quantity,
-                depth: depth,
-                unitPriceAnalysis: 1,
-            };
-            if (+unitPrice && +quantity) {
-                unitPrice = scMathUtil.roundForObj(unitPrice, decimalObj.bills.unitPrice);
-                const totalPrice = scMathUtil.roundForObj(unitPrice * +quantity, decimalObj.bills.totalPrice);
-                data.fees = [
-                    {
-                        fieldName: "common",
-                        tenderTotalFee: totalPrice,
-                        tenderUnitFee: unitPrice,
-                        totalFee: totalPrice,
-                        unitFee: unitPrice,
-                    }
-                ];
-                data.calcFlag = treeNodeCalcFlag.customUnitPrice;
-            }
-            //获取data的父节点链,成为兄弟节点,只能在父链里找前兄弟(不能跨父链)
-            let parents = getParents(lastData);
-            let preData = findLast(parents, x => x.depth === depth);
-            if (preData) {
-                preData.NextSiblingID = data.ID;
-                data.ParentID = preData.ParentID;
-                data.parent = preData.parent;
-            } else {
-                data.ParentID = lastData.ID;
-                data.parent = lastData;
-            }
-            rst.push(data);
+  }
 
-        }
-        console.log(rst);
-        return rst;
-        function getDepth(code) {
-            if (!code) {
-                return 1;
-            }
-            let match = code.match(/\s/g);
-            return match ? match.length + 1 : 1;
-        }
+  function getParents(data) {
+    let rst = [];
+    let parent = data.parent;
+    while (parent) {
+      rst.push(parent);
+      parent = parent.parent;
     }
+    rst.push(data);
+    return rst;
+  }
 
-    function getParents(data) {
-        let rst = [];
-        let parent = data.parent;
-        while (parent) {
-            rst.push(parent);
-            parent = parent.parent;
-        }
-        rst.push(data);
-        return rst;
+  //获取编号前缀: 101-1 => 101   101-1-1 => 101-1
+  function getPrefix(v) {
+    if (!v) {
+      return null;
     }
+    let reg = /(.*)-/;
+    let match = reg.exec(v);
+    return match ? match[1] : null;
+  }
 
-    //获取编号前缀: 101-1 => 101   101-1-1 => 101-1
-    function getPrefix(v) {
-        if (!v) {
-            return null;
-        }
-        let reg = /(.*)-/;
-        let match = reg.exec(v);
-        return match ? match[1] : null;
-    }
+  // 示例列映射
+  const slColMap = { code: 0, name: 1, unit: 2, quantity: 3, unitPrice: 4 };
 
-    // 示例列映射
-    const slColMap = { code: 0, name: 1, unit: 2, quantity: 3, unitPrice: 4 };
-
-    function isValidGCLExRow(rowData) {
-        if (rowData[0] && /编制[::]/.test(rowData[0].value)) {
-            return false;
-        }
-        if (rowData[1] && /合计/.test(rowData[1].value)) {
-            return false;
-        }
-        if ((!rowData[slColMap.code] || !rowData[slColMap.code].value) &&
-            (!rowData[slColMap.name] || !rowData[slColMap.name].value) &&
-            (!rowData[slColMap.unit] || !rowData[slColMap.unit].value) &&
-            (!rowData[slColMap.quantity] || !rowData[slColMap.quantity].value)) {
-            return false;
-        }
-        return true;
+  function isValidGCLExRow(rowData) {
+    if (rowData[0] && /编制[::]/.test(rowData[0].value)) {
+      return false;
     }
-
-    // 将“工程量清单预算表”去掉表头表尾,并转换成清单示例表。
-    // 工程量清单预算表的格式可参考需求:BUG #3037
-    function transformGCLExToSL(sheetData) {
-        const rst = {
-            data: { dataTable: [] },
-            rowCount: 0,
-        };
-        const dataTable = sheetData.data.dataTable;
-        const rowCount = sheetData.rows.length;
-        let preRootName;
-        for (let row = 0; row < rowCount; row++) {
-            const rowData = dataTable[row];
-            if (isGCLExtendHead(rowData, dataTable[row + 1])) {
-                const rootRowdata = dataTable[row + 3];
-                const name = rootRowdata[0].value;
-                if (name) {
-                    const rootName = name.replace('工程量清单', '清单');
-                    if (rootName !== preRootName) {
-                        preRootName = rootName;
-                        rst.data.dataTable.push({
-                            [slColMap.name]: { value: rootName }
-                        });
-                    }
-                }
-                row += 4;
-                continue;
-            }
-            if (isValidGCLExRow(rowData)) {
-                const cellData = {
-                    [slColMap.code]: { value: rowData[slColMap.code] && rowData[slColMap.code].value || null },
-                    [slColMap.name]: { value: rowData[slColMap.name] && rowData[slColMap.name].value || null },
-                    [slColMap.unit]: { value: rowData[slColMap.unit] && rowData[slColMap.unit].value || null },
-                    [slColMap.quantity]: { value: rowData[slColMap.quantity] && rowData[slColMap.quantity].value || null },
-                    [slColMap.unitPrice]: { value: rowData[slColMap.unitPrice] && rowData[slColMap.unitPrice].value || null },
-                };
-                rst.data.dataTable.push(cellData);
-            }
-        }
-        rst.rowCount = rst.data.dataTable.length;
-        return rst;
+    if (rowData[1] && /合计/.test(rowData[1].value)) {
+      return false;
     }
+    if (
+      (!rowData[slColMap.code] || !rowData[slColMap.code].value) &&
+      (!rowData[slColMap.name] || !rowData[slColMap.name].value) &&
+      (!rowData[slColMap.unit] || !rowData[slColMap.unit].value) &&
+      (!rowData[slColMap.quantity] || !rowData[slColMap.quantity].value)
+    ) {
+      return false;
+    }
+    return true;
+  }
 
-    //提取清单示例数据
-    function extractSLDatas(sheetData) {
-        let dataTable = sheetData.data.dataTable,
-            rowCount = sheetData.rows.length;
-        let rst = [];
-        let curRoot = null;
-        for (let row = 0; row < rowCount; row++) {
-            let code = dataTable[row][slColMap.code] && dataTable[row][slColMap.code].value ? String(dataTable[row][slColMap.code].value).trim() : null,
-                name = dataTable[row][slColMap.name] ? _deNR(dataTable[row][slColMap.name].value) : null,
-                unit = dataTable[row][slColMap.unit] ? dataTable[row][slColMap.unit].value : null,
-                quantity = dataTable[row][slColMap.quantity] ? dataTable[row][slColMap.quantity].value : null,
-                unitPrice = dataTable[row][slColMap.unitPrice] ? dataTable[row][slColMap.unitPrice].value : null;
-            if (!code) {    //没有编号的数据,名称必须为:清单 第xx章,认为新的表根节点
-                const reg = /清单\s+第[^章]+章/;
-                //if (name && /清单 第\d+章/.test(name)) {
-                if (name && reg.test(name)) {
-                    curRoot = {
-                        code: null,
-                        name: name,
-                        ID: uuid.v1(),
-                        ParentID: -1,
-                        NextSiblingID: -1,
-                        parent: null,
-                        unitPriceAnalysis: 1
-                    };
-                    rst.push(curRoot);
-                } else {
-                    curRoot = null;
-                }
-            } else if (!curRoot) {  //根节点为无效根节点,其下子数据全部过滤掉
-                continue;
-            } else {
-                //有code且有有效表根节点
-                let prefix = getPrefix(code);
-                let data = {
-                    code: code,
-                    name: name,
-                    unit: unit,
-                    quantity: quantity,
-                    quantityEXP: "" + quantity,
-                    ID: uuid.v1(),
-                    NextSiblingID: -1,
-                    unitPriceAnalysis: 1
-                };
-                if (+unitPrice && +quantity) {
-                    unitPrice = scMathUtil.roundForObj(unitPrice, decimalObj.bills.unitPrice);
-                    const totalPrice = scMathUtil.roundForObj(unitPrice * +quantity, decimalObj.bills.totalPrice);
-                    data.fees = [
-                        {
-                            fieldName: "common",
-                            tenderTotalFee: totalPrice,
-                            tenderUnitFee: unitPrice,
-                            totalFee: totalPrice,
-                            unitFee: unitPrice,
-                        }
-                    ];
-                    data.calcFlag = treeNodeCalcFlag.customUnitPrice;
-                }
-                let lastData = rst[rst.length - 1];
-                let parents = getParents(lastData);
-                //某数据编号为此数据的前缀,则某数据为此数据的父节点
-                let parentData = findLast(parents, x => prefix === x.code);
-                if (!parentData && prefix === '') { // -x的数据,在父链上找不到编号与prefix相同的数据时,父链上-x的数据,则这两数据为兄弟节点,没有则上一行数据为其父节点
-                    let samePrefixData = findLast(parents, x => getPrefix(x.code) === prefix);
-                    parentData = samePrefixData ? samePrefixData.parent : lastData;
-                } else if (!parentData && prefix !== '') {  //不是-x的数据,在父链上找不到编号与prefix相同的数据时,表根节点为其父节点
-                    parentData = curRoot;
-                }
-                data.ParentID = parentData.ID;
-                data.parent = parentData;
-                let preData = findLast(parents, x => x.ParentID === data.ParentID);
-                if (preData) {
-                    preData.NextSiblingID = data.ID;
-                }
-                rst.push(data);
-            }
+  // 将“工程量清单预算表”去掉表头表尾,并转换成清单示例表。
+  // 工程量清单预算表的格式可参考需求:BUG #3037
+  function transformGCLExToSL(sheetData) {
+    const rst = {
+      data: { dataTable: [] },
+      rowCount: 0,
+    };
+    const dataTable = sheetData.data.dataTable;
+    const rowCount = sheetData.rows.length;
+    let preRootName;
+    for (let row = 0; row < rowCount; row++) {
+      const rowData = dataTable[row];
+      if (isGCLExtendHead(rowData, dataTable[row + 1])) {
+        const rootRowdata = dataTable[row + 3];
+        const name = rootRowdata[0].value;
+        if (name) {
+          const rootName = name.replace("工程量清单", "清单");
+          if (rootName !== preRootName) {
+            preRootName = rootName;
+            rst.data.dataTable.push({
+              [slColMap.name]: { value: rootName },
+            });
+          }
         }
-        console.log(rst);
-        return rst;
+        row += 4;
+        continue;
+      }
+      if (isValidGCLExRow(rowData)) {
+        const cellData = {
+          [slColMap.code]: { value: (rowData[slColMap.code] && rowData[slColMap.code].value) || null },
+          [slColMap.name]: { value: (rowData[slColMap.name] && rowData[slColMap.name].value) || null },
+          [slColMap.unit]: { value: (rowData[slColMap.unit] && rowData[slColMap.unit].value) || null },
+          [slColMap.quantity]: { value: (rowData[slColMap.quantity] && rowData[slColMap.quantity].value) || null },
+          [slColMap.unitPrice]: { value: (rowData[slColMap.unitPrice] && rowData[slColMap.unitPrice].value) || null },
+        };
+        rst.data.dataTable.push(cellData);
+      }
     }
+    rst.rowCount = rst.data.dataTable.length;
+    return rst;
+  }
 
-    function extactDatas(sheets) {
-        let rst = [];
-        let curSheetType = null;
-        for (let sheetName in sheets) {
-            let sheetData = sheets[sheetName];
-            if (!sheetData.data.dataTable || sheetData.index !== 0) {
-                continue;
-            }
-            let sheetType = getFileType(sheetData);
-            if (curSheetType !== null && sheetType !== curSheetType) {
-                throw 'excel文件中存在不同格式的表格。';
-            }
-            curSheetType = sheetType;
-            let colMapping = getColMapping(sheetType);
-            let datas = [];
-            if (sheetType === fileType.gcl) {
-                datas = extractGCLDatas(sheetData, colMapping);
-            } else if (sheetType === fileType.qdsl) {
-                datas = extractSLDatas(sheetData, colMapping);
-            } else {
-                const slSheetData = transformGCLExToSL(sheetData);
-                datas = extractSLDatas(slSheetData, colMapping);
-            }
-            rst = rst.concat(datas);
+  //提取清单示例数据
+  function extractSLDatas(sheetData) {
+    let dataTable = sheetData.data.dataTable,
+      rowCount = sheetData.rows.length;
+    let rst = [];
+    let curRoot = null;
+    for (let row = 0; row < rowCount; row++) {
+      let code = dataTable[row][slColMap.code] && dataTable[row][slColMap.code].value ? String(dataTable[row][slColMap.code].value).trim() : null,
+        name = dataTable[row][slColMap.name] ? _deNR(dataTable[row][slColMap.name].value) : null,
+        unit = dataTable[row][slColMap.unit] ? dataTable[row][slColMap.unit].value : null,
+        quantity = dataTable[row][slColMap.quantity] ? dataTable[row][slColMap.quantity].value : null,
+        unitPrice = dataTable[row][slColMap.unitPrice] ? dataTable[row][slColMap.unitPrice].value : null;
+      if (!code) {
+        //没有编号的数据,名称必须为:清单 第xx章,认为新的表根节点
+        const reg = /清单\s+第[^章]+章/;
+        //if (name && /清单 第\d+章/.test(name)) {
+        if (name && reg.test(name)) {
+          curRoot = {
+            code: null,
+            name: name,
+            ID: uuid.v1(),
+            ParentID: -1,
+            NextSiblingID: -1,
+            parent: null,
+            unitPriceAnalysis: 1,
+          };
+          rst.push(curRoot);
+        } else {
+          curRoot = null;
         }
-        //编号去除空格 清除多余数据 设置数据
-        for (let data of rst) {
-            if (data.code && typeof data.code === 'string') {
-                data.code = data.code.replace(/\s/g, '');
-            }
-            if (data.unit === '㎡') {
-                data.unit = 'm2';
-            } else if (data.unit === 'm³') {
-                data.unit = 'm3';
-            }
-            data.projectID = projectObj.project.ID();
-            data.type = billType.BILL;
-            delete data.parent;
-            delete data.depth;
+      } else if (!curRoot) {
+        //根节点为无效根节点,其下子数据全部过滤掉
+        continue;
+      } else {
+        //有code且有有效表根节点
+        let prefix = getPrefix(code);
+        let data = {
+          code: code,
+          name: name,
+          unit: unit,
+          quantity: quantity,
+          quantityEXP: "" + quantity,
+          ID: uuid.v1(),
+          NextSiblingID: -1,
+          unitPriceAnalysis: 1,
+        };
+        if (+unitPrice && +quantity) {
+          unitPrice = scMathUtil.roundForObj(unitPrice, decimalObj.bills.unitPrice);
+          const totalPrice = scMathUtil.roundForObj(unitPrice * +quantity, decimalObj.bills.totalPrice);
+          data.fees = [
+            {
+              fieldName: "common",
+              tenderTotalFee: totalPrice,
+              tenderUnitFee: unitPrice,
+              totalFee: totalPrice,
+              unitFee: unitPrice,
+            },
+          ];
+          data.calcFlag = treeNodeCalcFlag.customUnitPrice;
         }
-        //将表根节点的ParentID设置成第100章至700章清单的ID
-        let fixedBill = projectObj.project.Bills.tree.roots.find(node => node.data &&
-            node.data.flagsIndex && node.data.flagsIndex.fixed && node.data.flagsIndex.fixed.flag === fixedFlag.ONE_SEVEN_BILLS);
-        let rootDatas = rst.filter(data => data.ParentID === -1);
-        for (let root of rootDatas) {
-            root.ParentID = fixedBill.data.ID;
+        let lastData = rst[rst.length - 1];
+        let parents = getParents(lastData);
+        //某数据编号为此数据的前缀,则某数据为此数据的父节点
+        let parentData = findLast(parents, (x) => prefix === x.code);
+        if (!parentData && prefix === "") {
+          // -x的数据,在父链上找不到编号与prefix相同的数据时,父链上-x的数据,则这两数据为兄弟节点,没有则上一行数据为其父节点
+          let samePrefixData = findLast(parents, (x) => getPrefix(x.code) === prefix);
+          parentData = samePrefixData ? samePrefixData.parent : lastData;
+        } else if (!parentData && prefix !== "") {
+          //不是-x的数据,在父链上找不到编号与prefix相同的数据时,表根节点为其父节点
+          parentData = curRoot;
         }
-        //清单 第100章 总则清单需要加上固定ID
-        let oneHundredBills = rootDatas.find(data => data.name && /第100章/.test(data.name));
-        if (oneHundredBills) {
-            oneHundredBills.flags = [{ flag: fixedFlag.ONE_HUNDRED_BILLS, fieldName: 'fixed' }];
+        data.ParentID = parentData.ID;
+        data.parent = parentData;
+        let preData = findLast(parents, (x) => x.ParentID === data.ParentID);
+        if (preData) {
+          preData.NextSiblingID = data.ID;
         }
-        return rst;
+        rst.push(data);
+      }
+    }
+    console.log(rst);
+    return rst;
+  }
+
+  function extactDatas(sheets) {
+    let rst = [];
+    let curSheetType = null;
+    for (let sheetName in sheets) {
+      let sheetData = sheets[sheetName];
+      if (!sheetData.data.dataTable || sheetData.index !== 0) {
+        continue;
+      }
+      let sheetType = getFileType(sheetData);
+      if (curSheetType !== null && sheetType !== curSheetType) {
+        throw "excel文件中存在不同格式的表格。";
+      }
+      curSheetType = sheetType;
+      let colMapping = getColMapping(sheetType);
+      let datas = [];
+      if (sheetType === fileType.gcl) {
+        datas = extractGCLDatas(sheetData, colMapping);
+      } else if (sheetType === fileType.qdsl) {
+        datas = extractSLDatas(sheetData, colMapping);
+      } else {
+        const slSheetData = transformGCLExToSL(sheetData);
+        datas = extractSLDatas(slSheetData, colMapping);
+      }
+      rst = rst.concat(datas);
+    }
+    //编号去除空格 清除多余数据 设置数据
+    for (let data of rst) {
+      if (data.code && typeof data.code === "string") {
+        data.code = data.code.replace(/\s/g, "");
+      }
+      if (data.unit === "㎡") {
+        data.unit = "m2";
+      } else if (data.unit === "m³") {
+        data.unit = "m3";
+      }
+      data.projectID = projectObj.project.ID();
+      data.type = billType.BILL;
+      delete data.parent;
+      delete data.depth;
+    }
+    //将表根节点的ParentID设置成第100章至700章清单的ID
+    let fixedBill = projectObj.project.Bills.tree.roots.find(
+      (node) => node.data && node.data.flagsIndex && node.data.flagsIndex.fixed && node.data.flagsIndex.fixed.flag === fixedFlag.ONE_SEVEN_BILLS
+    );
+    let rootDatas = rst.filter((data) => data.ParentID === -1);
+    for (let root of rootDatas) {
+      root.ParentID = fixedBill.data.ID;
+    }
+    //清单 第100章 总则清单需要加上固定ID
+    let oneHundredBills = rootDatas.find((data) => data.name && /第100章/.test(data.name));
+    if (oneHundredBills) {
+      oneHundredBills.flags = [{ flag: fixedFlag.ONE_HUNDRED_BILLS, fieldName: "fixed" }];
     }
+    return rst;
+  }
 
-    return { extactDatas }
-})();
+  return { extactDatas };
+})();

Разница между файлами не показана из-за своего большого размера
+ 1758 - 1557
web/building_saas/main/js/views/project_glj_view.js


+ 93 - 92
web/building_saas/main/js/views/project_info.js

@@ -2,57 +2,59 @@
  * Created by Mai on 2017/6/21.
  */
 
-const { 
-    ValuationType: { BUDGET, BOQ },
+const {
+  ValuationType: { BUDGET, BOQ },
 } = window.commonConstants;
 
 var projectInfoObj = {
-    // 头部同时编辑的用户头像
-    handleAvatarList: function (users) {
-        const opener = projectObj.project.projectInfo.opener;
-        if (opener) {
-            users = users.filter(user => user._id !== opener._id);
-        }
-        const avatarListHtml = users.reduce((acc, user) => {
-            const avatarSpan = SHARE_TO.getAvatarHTML(user.mobile, user.real_name);
-            const li =
-                `<li data-toggle="tooltip" data-placement="bottom" title="${user.real_name}" data-original-title="${user.real_name}">
+  // 头部同时编辑的用户头像
+  handleAvatarList: function (users) {
+    const opener = projectObj.project.projectInfo.opener;
+    if (opener) {
+      users = users.filter((user) => user._id !== opener._id);
+    }
+    const avatarListHtml = users.reduce((acc, user) => {
+      const avatarSpan = SHARE_TO.getAvatarHTML(user.mobile, user.real_name);
+      const li = `<li data-toggle="tooltip" data-placement="bottom" title="${user.real_name}" data-original-title="${user.real_name}">
                         ${avatarSpan}
-                    </li>`
-            return acc += li;
-        }, '');
-        $('#avatar-list').html(avatarListHtml);
-        $('#avatar-list [data-toggle="tooltip"]').tooltip();
-    },
-    getReceiveInfo: function (projectReadOnly, projectCooperate, owner) {
-        if (!projectReadOnly && !projectCooperate) {
-            return '';
-        }
-        const action = projectCooperate ? '可编辑' : '只能查看';
-        const ownerName = owner && owner.real_name || '';
-        return `
+                    </li>`;
+      return (acc += li);
+    }, "");
+    $("#avatar-list").html(avatarListHtml);
+    $('#avatar-list [data-toggle="tooltip"]').tooltip();
+  },
+  getReceiveInfo: function (projectReadOnly, projectCooperate, owner) {
+    if (!projectReadOnly && !projectCooperate) {
+      return "";
+    }
+    const action = projectCooperate ? "可编辑" : "只能查看";
+    const ownerName = (owner && owner.real_name) || "";
+    return `
                 <span class="pl-2" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="来自 ${ownerName} 的分享">
                     <a href="javascript:;" class="btn btn-xs btn-primary default-cursor"><i class="fa fa-share-alt"></i> ${action}</a>
                 </span>`;
-    },
-    getShareButton: function (projectReadOnly, projectCooperate, shareTip) {
-        if (projectReadOnly || projectCooperate) {
-            return '';
-        }
-        return `
+  },
+  getShareButton: function (projectReadOnly, projectCooperate, shareTip) {
+    if (projectReadOnly || projectCooperate) {
+      return "";
+    }
+    return `
                 <span id="share-tip" class="ml-2" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="${shareTip}">
                     <a id="init-share" href="javascript:;" class="btn btn-xs btn-primary"><i class="fa fa-share-alt"></i> 分享</a>
                 </span>`;
-    },
-    getFullPathHtml: function (proj) {
-        let fullPath = [], i, pm = '<span class="text-truncate"><a href="/pm">项目管理</a></span>', angleRight = '<span class="text-truncate"><i class="fa fa-angle-right fa-fw"></i></span>';
-        if (proj) {
-            let pathArr = proj.fullPath;
-            let projectName = pathArr[pathArr.length - 2] || '',
-                folderName = pathArr[pathArr.length - 3] || '';
-            const receiveInfo = this.getReceiveInfo(projectReadOnly, projectCooperate, proj.owner);
-            const shareButton = this.getShareButton(projectReadOnly, projectCooperate, proj.shareTip);
-            let newHtml = `   <span data-toggle="tooltip" data-placement="bottom" data-original-title="${folderName}"><i class="fa fa-folder-open-o"></i>...</span>
+  },
+  getFullPathHtml: function (proj) {
+    let fullPath = [],
+      i,
+      pm = '<span class="text-truncate"><a href="/pm">项目管理</a></span>',
+      angleRight = '<span class="text-truncate"><i class="fa fa-angle-right fa-fw"></i></span>';
+    if (proj) {
+      let pathArr = proj.fullPath;
+      let projectName = pathArr[pathArr.length - 2] || "",
+        folderName = pathArr[pathArr.length - 3] || "";
+      const receiveInfo = this.getReceiveInfo(projectReadOnly, projectCooperate, proj.owner);
+      const shareButton = this.getShareButton(projectReadOnly, projectCooperate, proj.shareTip);
+      let newHtml = `   <span data-toggle="tooltip" data-placement="bottom" data-original-title="${folderName}"><i class="fa fa-folder-open-o"></i>...</span>
                 <span class="text-muted px-1">\</span>
                 <span data-toggle="tooltip" data-placement="bottom" data-original-title="${projectName}"><i class="fa fa-cubes"></i>...</span>
                 <span class="text-muted px-1">\</span>
@@ -64,59 +66,58 @@ var projectInfoObj = {
                     </ul>
                 </span>
                 `;
-            fullPath.push(newHtml);
-
-        }
-        return fullPath.join('');
-    },
-    showProjectInfo: function (data) {
-        if (data) {
-            //如果是工程量清单项目,则显示导入、分摊功能
-            if (data.property.valuationType === 'ration' || data.property.valuationType === 'bill_budget') {
-                $('#importSpan').show();
-                $('#tab_divide').show();
-            }
+      fullPath.push(newHtml);
+    }
+    return fullPath.join("");
+  },
+  showProjectInfo: function (data) {
+    if (data) {
+      //如果是工程量清单项目,则显示导入、分摊功能
+      if (data.property.valuationType === "ration" || data.property.valuationType === "bill_budget") {
+        $("#importSpan").show();
+        $("#tab_divide").show();
+      }
 
-            //打开预算项目时,右侧“清单规则”显示为“项目表”,打开工程量清单项目时,右侧“清单规则”显示为“清单范本”。
-            $('#stdBillsGuidanceTab').text(data.property.valuationType === BOQ ? '清单范本' : '项目表');
-            //init decimal
-            setDecimal(decimalObj, data.property.decimal);
-            billsQuanDecimal.datas = data.property.billsQuantityDecimal || [billsDecimalView.angleDecimal];
-            // 建设项目为工程量清单项目显示基本信息,预算项目不显示
-            if (data.property.projectValuationType !== BOQ) {
-                // 隐藏基本信息
-                $('#tab_poj-settings-basicInfo').removeClass('active');
-                $('#tab_poj-settings-basicInfo').hide();
-                $('#poj-settings-basicInfo').removeClass('show');
-                $('#poj-settings-basicInfo').removeClass('active');
-                // 显示工程特征
-                $('#tab_poj-settings-projFeature').addClass('active');
-                $('#poj-settings-projFeature').addClass('show');
-                $('#poj-settings-projFeature').addClass('active');
-            }
-            basicInfoView.orgDatas = data.property.basicInformation ? basicInfoView.toViewDatas(data.property.basicInformation) : [];
-            projFeatureView.orgDatas = data.property.projectFeature ? projFeatureView.toViewDatas(data.property.projectFeature) : [];
-            $('#fullpath').html(this.getFullPathHtml(data));
-            // 分享给
-            $('#init-share').click(() => {
-                SHARE_TO.initModal(SHARE_TO.Mode.PROJECT, projectObj.project.ID());
-                $('#share-tip').tooltip('hide');
-            });
-            SHARE_TO.handleEventListener();
-            $("[data-toggle='tooltip']").tooltip();
-            if (data.property.valuationType !== BOQ && data.property.valuationType !== 'bill_budget') {
-                $("#tab_tender_price").css('display', 'none');
-            }/*  else {
+      //打开预算项目时,右侧“清单规则”显示为“项目表”,打开工程量清单项目时,右侧“清单规则”显示为“清单范本”。
+      $("#stdBillsGuidanceTab").text(data.property.valuationType === BOQ ? "清单范本" : "项目表");
+      //init decimal
+      setDecimal(decimalObj, data.property.decimal);
+      billsQuanDecimal.datas = data.property.billsQuantityDecimal || [billsDecimalView.angleDecimal];
+      // 建设项目为工程量清单项目显示基本信息,预算项目不显示
+      if (data.property.projectValuationType !== BOQ) {
+        // 隐藏基本信息
+        $("#tab_poj-settings-basicInfo").removeClass("active");
+        $("#tab_poj-settings-basicInfo").hide();
+        $("#poj-settings-basicInfo").removeClass("show");
+        $("#poj-settings-basicInfo").removeClass("active");
+        // 显示工程特征
+        $("#tab_poj-settings-projFeature").addClass("active");
+        $("#poj-settings-projFeature").addClass("show");
+        $("#poj-settings-projFeature").addClass("active");
+      }
+      basicInfoView.orgDatas = data.property.basicInformation ? basicInfoView.toViewDatas(data.property.basicInformation) : [];
+      projFeatureView.orgDatas = data.property.projectFeature ? projFeatureView.toViewDatas(data.property.projectFeature) : [];
+      $("#fullpath").html(this.getFullPathHtml(data));
+      // 分享给
+      $("#init-share").click(() => {
+        SHARE_TO.initModal(SHARE_TO.Mode.PROJECT, projectObj.project.ID());
+        $("#share-tip").tooltip("hide");
+      });
+      SHARE_TO.handleEventListener();
+      $("[data-toggle='tooltip']").tooltip();
+      if (data.property.valuationType !== BOQ && data.property.valuationType !== "bill_budget") {
+        $("#tab_tender_price").css("display", "none");
+      } /*  else {
                 $("#about-calc").css('display', 'none');
             }; */
-        }
-    },
-    // 刷新总造价显示span
-    refreshTotalPriceSpan: function () {
-        const totalNode = projectObj.project.mainTree.roots.find(node => node.getFlag() === fixedFlag.TOTAL_COST);
-        const price = totalNode ? calcTools.getFee(totalNode, 'common.tenderTotalFee') : '0';
-        const standardPrice = commonUtil.standardNumber(price);
-        const text = `总造价:${standardPrice} 元`;
-        $('#total-price-span').text(text);
     }
+  },
+  // 刷新总造价显示span
+  refreshTotalPriceSpan: function () {
+    const totalNode = projectObj.project.mainTree.roots.find((node) => node.getFlag() === fixedFlag.TOTAL_COST);
+    const price = totalNode ? calcTools.getFee(totalNode, "common.tenderTotalFee") : "0";
+    const standardPrice = commonUtil.standardNumber(price);
+    const text = `总造价:${standardPrice} 元`;
+    $("#total-price-span").text(text);
+  },
 };

+ 4 - 1
web/building_saas/main/js/views/project_view.js

@@ -1313,7 +1313,10 @@ var projectObj = {
       spread = this.mainSpread,
       controller = this.mainController;
     let insertBillsName =
-      project.projectInfo.property && project.projectInfo.property.valuationType == commonConstants.ValuationType.BOQ ? "插入清单" : "插入项目节"; //右键“插入清单”改文字为“插入项目节”,工程量清单中保持不变。
+      project.projectInfo.property &&
+      [commonConstants.ValuationType.BOQ, commonConstants.ValuationType.BILL_BUDGET].includes(project.projectInfo.property.valuationType)
+        ? "插入清单"
+        : "插入项目节"; //右键“插入清单”改文字为“插入项目节”,工程量清单中保持不变。
     $.contextMenu({
       selector: "#billsSpread",
       selectableSubMenu: true,

Разница между файлами не показана из-за своего большого размера
+ 1295 - 1282
web/building_saas/main/js/views/std_billsGuidance_lib.js


+ 33 - 126
web/over_write/js/sichuan_2013.js

@@ -57,7 +57,7 @@ const progression = ["养护单位管理费"];
 const deficiency = {};
 if (typeof baseFigureMap !== "undefined") {
   const { fixedFlag } = commonConstants;
-  const budgetMap = {
+  const boqMap = {
     // 显示:除清单固定类别是“公路养护工程费”的以外部分可显示
     公路养护工程费: {
       base: "GLYHGCF",
@@ -65,13 +65,6 @@ if (typeof baseFigureMap !== "undefined") {
       filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE],
       pick: false,
     },
-    // 显示:除清单固定类别是“公路养护工程费”的以外部分可显示
-    // 定额公路养护工程费: {
-    //   base: "DEGLYHGCF",
-    //   fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
-    //   filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE],
-    //   pick: false,
-    // },
     "养护工程费(不含保险费、施工环保水保费、安全生产费)": {
       base: "YHGCFBHBXHBSBAQ",
       fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
@@ -86,13 +79,13 @@ if (typeof baseFigureMap !== "undefined") {
       filter: [fixedFlag.MAINTENANCE_EXPENSES],
       pick: true,
     },
-    // 显示:除清单固定类别是“公路养护工程费”、“设备购置费用”、“养护公路工程其他费用”、“一二三部分合计”的以外部分可显示
-    /*     "一、二、三部分合计": {
+    // {一、二、三部分合计} 只显示在 预备费及其子项下
+    "一、二、三部分合计": {
       base: "YESBFHJ",
-      fixedFlag: fixedFlag.ONE_TO_THREE_TOTAL,
-      filter: [fixedFlag.ONE_TO_THREE_TOTAL],
-      pick: false,
-    }, */
+      fixedFlag: null,
+      filter: [fixedFlag.BUDGET_FEE],
+      pick: true,
+    },
     // 显示:仅“价差预备费”可显示
     价差预备费: {
       base: "JCYBF",
@@ -100,24 +93,6 @@ if (typeof baseFigureMap !== "undefined") {
       filter: [fixedFlag.SPREAD_BUDGET_FEE],
       pick: true,
     },
-    // 通则扣除保险费: {
-    //   base: "TEXT1",
-    //   fixedFlag: null,
-    //   filter: [fixedFlag.INSURANCE_FEE],
-    //   pick: true,
-    // },
-    // 扣除安全生产费: {
-    //   base: "TEXT2",
-    //   fixedFlag: null,
-    //   filter: [fixedFlag.EP_WP_INSURANCE_FEE],
-    //   pick: true,
-    // },
-    // 扣除保险费: {
-    //   base: "TEXT3",
-    //   fixedFlag: null,
-    //   filter: [fixedFlag.SAFE_COST],
-    //   pick: true,
-    // },
     预算和标底审核费: {
       base: "YSHBDSHF",
       fixedFlag: null,
@@ -142,8 +117,6 @@ if (typeof baseFigureMap !== "undefined") {
       filter: [fixedFlag.MAINTENANCE_EXPENSES],
       pick: true,
     },
-  };
-  const boqMap = {
     //四川2013读的是 建筑安装工程费行的值
     各章清单合计: {
       base: "GZQDHJ",
@@ -151,25 +124,7 @@ if (typeof baseFigureMap !== "undefined") {
       filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE],
       pick: false,
     },
-    // 显示:仅清单固定类别是“养护工程其他费用”部分可显示。
-    养护单位管理费: {
-      isProgressive: true,
-      base: "YHDWGLF",
-      fixedFlag: null,
-      filter: [fixedFlag.MAINTENANCE_EXPENSES],
-      pick: true,
-    },
-    //仅允许用于固定类别是“第100章至700章清单”以外的清单
-    /*     '专项暂定合计': {
-          base: 'ZXZDHJ',
-          fixedFlag: null,
-          filter: [fixedFlag.ONE_SEVEN_BILLS],
-          pick: false
-      }, */
-    /*
-     *  清单固定行[第100章至700章清单]下的[第100章清单]需要允许清单可使用基数{100章以外合计}
-     *  因此{100章以外合计}不设置关联的清单固定行
-     * */
+    // 清单固定行[第100章至700章清单]下的[第100章清单]需要允许清单可使用基数{100章以外合计},因此{100章以外合计}不设置关联的清单固定行
     //仅允许用于固定类别为“100章清单”引用
     "100章以外清单合计": {
       base: "YBZYHQDHJ",
@@ -178,21 +133,17 @@ if (typeof baseFigureMap !== "undefined") {
       pick: true,
     },
   };
-  baseFigureMap.budget = budgetMap;
   baseFigureMap.boq = boqMap;
 }
 
 if (typeof baseFigureTemplate !== "undefined") {
   const { fixedFlag } = commonConstants;
-  baseFigureTemplate.budget = {
+  baseFigureTemplate.boq = {
     // 公路养护工程费 算法:取清单固定类别是“建筑安装工程费”的金额。
     GLYHGCF(tender) {
       return cbTools.getBaseFee(fixedFlag.CONSTRUCTION_INSTALL_FEE, tender, "common");
     },
-    // 定额公路养护工程费 算法:取清单固定类别是“建筑安装工程费”的金额。
-    DEGLYHGCF(tender) {
-      return cbTools.getBaseFee(fixedFlag.CONSTRUCTION_INSTALL_FEE, tender, "rationCommon");
-    },
+    // 养护工程费(不含保险费、施工环保水保费、安全生产费
     YHGCFBHBXHBSBAQ(tender) {
       const baseFee = cbTools.getBaseFee(fixedFlag.CONSTRUCTION_INSTALL_FEE, tender, "common");
       const fee1 = cbTools.getBaseFee(fixedFlag.INSURANCE_FEE, tender, "common");
@@ -215,26 +166,27 @@ if (typeof baseFigureTemplate !== "undefined") {
         deficiency
       );
     },
-    // 二三部分合计 算法:取清单固定类别是“一二三部分合计”的金额
+    // 二三部分合计 算法:取清单固定类别是“一二三部分合计”的金额
     YESBFHJ(tender) {
       return cbTools.getBaseFee(fixedFlag.ONE_TO_THREE_TOTAL, tender, "common");
     },
-    TEXT1(tender) {
-      const baseFee = cbTools.getBaseFee(fixedFlag.CONSTRUCTION_INSTALL_FEE, tender, "common");
-      const fullFeeField = tender ? `${feeField}.tenderTotalFee` : `${feeField}.totalFee`;
-      let genRuleNode = this.findNodeByFlag(fixedFlag.GENERAL_RULE);
-      if (!genRuleNode) {
-        return baseFee;
-      }
-      const deductionFee = projectObj.project.calcProgram.getTotalFee([genRuleNode], [calcBase.activeNode], fullFeeField);
-      return (baseFee - deductionFee).toDecimal(decimalObj.bills.totalPrice);
-    },
-    TEXT2(tender) {
-      return cbTools.getFeeWithDeduction(fixedFlag.CONSTRUCTION_INSTALL_FEE, [fixedFlag.SAFE_COST], tender, "common");
-    },
-    TEXT3(tender) {
-      return cbTools.getFeeWithDeduction(fixedFlag.CONSTRUCTION_INSTALL_FEE, [fixedFlag.INSURANCE_FEE], tender, "common");
+    /*  价差预备费 算法:以建筑安装工程费为基数,按设计文件编制年始至养护项目工程竣工年终的年数和年工程造价增涨率计算。
+          价差预备费 P * [(1+i)^(n-1) -1]
+          P——建筑安装工程费总额(元);
+          i——年工程造价增涨率(%);
+          n——设计文件编制年至养护项目开工年+养护项目建设期限(年)。
+      */
+    JCYBF(tender) {
+      //公路养护工程费(即建筑安装工程费)作为基数
+      const installFee = this["GLYHGCF"](tender);
+      //年造价增涨
+      const costGrowthRate = calcBase.project.property.costGrowthRate ? calcBase.project.property.costGrowthRate : 0;
+      //增涨计费年限
+      const growthPeriod = projectObj.project.property.growthPeriod ? calcBase.project.property.growthPeriod : 0;
+      //= P * [(1+i)^(n-1) -1]
+      return (installFee * (Math.pow(1 + costGrowthRate, growthPeriod - 1) - 1)).toDecimal(decimalObj.bills.totalPrice);
     },
+    // 预算和标底审核费
     YSHBDSHF(tender) {
       const baseFee = this["GLYHGCF"](tender);
       if (!tender) {
@@ -248,6 +200,7 @@ if (typeof baseFigureTemplate !== "undefined") {
         deficiency
       );
     },
+    // 独立桥隧及地质病害工程养护工程设计费
     DLQSJDZBHGCYHGCSJF(tender) {
       const baseFee = this["GLYHGCF"](tender);
       if (!tender) {
@@ -261,6 +214,7 @@ if (typeof baseFigureTemplate !== "undefined") {
         deficiency
       );
     },
+    // 路基路面及其他工程养护工程设计费
     LJLMJQTGCYHGCSJF(tender) {
       const baseFee = this["GLYHGCF"](tender);
       if (!tender) {
@@ -274,6 +228,7 @@ if (typeof baseFigureTemplate !== "undefined") {
         deficiency
       );
     },
+    // 预算标底编制费
     YSBDBZF(tender) {
       const baseFee = this["GLYHGCF"](tender);
       if (!tender) {
@@ -287,63 +242,15 @@ if (typeof baseFigureTemplate !== "undefined") {
         deficiency
       );
     },
-    // 基本预备费 算法:以第一、二、三部分费用之和为基数按3%计取
-    JBYBF(tender) {
-      const baseFee = this["YESBFHJ"](tender);
-      return (baseFee * 0.03).toDecimal(decimalObj.bills.totalPrice);
-    },
-    /*  价差预备费 算法:以建筑安装工程费为基数,按设计文件编制年始至养护项目工程竣工年终的年数和年工程造价增涨率计算。
-          价差预备费 P * [(1+i)^(n-1) -1]
-          P——建筑安装工程费总额(元);
-          i——年工程造价增涨率(%);
-          n——设计文件编制年至养护项目开工年+养护项目建设期限(年)。
-      */
-    JCYBF(tender) {
-      //建筑安装工程费作为基数
-      const installFee = this["JZAZGCF"](tender);
-      //年造价增涨
-      const costGrowthRate = calcBase.project.property.costGrowthRate ? calcBase.project.property.costGrowthRate : 0;
-      //增涨计费年限
-      const growthPeriod = projectObj.project.property.growthPeriod ? calcBase.project.property.growthPeriod : 0;
-      //= P * [(1+i)^(n-1) -1]
-      return (installFee * (Math.pow(1 + costGrowthRate, growthPeriod - 1) - 1)).toDecimal(decimalObj.bills.totalPrice);
-    },
-  };
-
-  baseFigureTemplate.boq = {
-    // 公路养护工程费 算法:取清单固定类别是“建筑安装工程费”的金额。
-    GLYHGCF: function (tender) {
-      return cbTools.getBaseFee(fixedFlag.CONSTRUCTION_INSTALL_FEE, tender, "common");
-    },
     //{各章清单合计}
     // 四川2013读的是 建筑安装工程费行的值
     GZQDHJ: function (tender) {
       return cbTools.getBaseFee(fixedFlag.CONSTRUCTION_INSTALL_FEE, tender, "common");
     },
-    // 养护单位管理费 算法:以{公路养护工程费总额}为基数,采用累进办法计算
-    YHDWGLF: function (tender) {
-      const baseFee = this["GLYHGCF"](tender);
-      if (!tender) {
-        calcBase.baseProgressiveFee = baseFee;
-      }
-      return calculateUtil.getProgressiveFee(
-        baseFee,
-        "养护单位管理费",
-        projectObj.project.property.progressiveInterval,
-        decimalObj.bills.totalPrice,
-        deficiency
-      );
-    },
-    //{专项暂定合计}
-    // 第100章至700章清单行的暂估合价
-    ZXZDHJ: function (tender) {
-      return cbTools.getBaseFee(calcBase.fixedFlag.ONE_SEVEN_BILLS, tender, "estimate");
-    },
-    //{100章以外清单合计}
-    // 取清单固定清单[第100章至700章清单]的金额,但扣除清单100章下的金额。
-    // 如果是固定清单[第100章至700章清单]下100章以外清单引用此基数,要排除自身(目前只允许100章的清单使用,所以暂时不需要此判断)
+    //{100章以外清单合计} 取清单固定清单[第100章至700章清单]的金额,但扣除清单100章下的金额。如果是固定清单[第100章至700章清单]下100章以外清单引用此基数,要排除自身(目前只允许100章的清单使用,所以暂时不需要此判断)
     YBZYHQDHJ: function (tender) {
-      let oneToSeven = cbTools.findNodeByFlag(fixedFlag.ONE_SEVEN_BILLS);
+      // let oneToSeven = cbTools.findNodeByFlag(fixedFlag.ONE_SEVEN_BILLS); // 少了清单“第100章至700章清单”, 直接取“第一部分 公路养护工程费”
+      let oneToSeven = cbTools.findNodeByFlag(fixedFlag.CONSTRUCTION_INSTALL_FEE);
       if (!oneToSeven) {
         return 0;
       }