Browse Source

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

zhangweicheng 4 năm trước cách đây
mục cha
commit
38eae3d7a5

+ 1 - 1
modules/main/controllers/bills_controller.js

@@ -189,7 +189,7 @@ module.exports = {
     downloadExample: function(request, response) {
         try {
             //导入类型(09表、广联达)对应的示例文件名
-            const uploadTypeMap = { lj: '分部分项工程项目清单计价表.xlsx', gld: '算量示例-清单汇总表.xlsx' };
+            const uploadTypeMap = { general: '示例1-分部分项工程项目清单.xlsx', lj: '示例2-分部分项工程项目清单计价表.xlsx', gld: '算量示例-清单汇总表.xlsx' };
             const type = request.query.type;
             const fileName = uploadTypeMap[type];
             const filePath = `./public/static/${fileName}`;

+ 2 - 2
package.json

@@ -34,8 +34,8 @@
     "gulp-load-plugins": "^0.10.0",
     "gulp-plumber": "^1.0.1",
     "gulp-size": "^1.2.1",
-    "gulp-uglify": "^1.1.0",
-    "gulp-uglify-es": "^0.1.3",
+    "gulp-uglify": "^3.0.2",
+    "gulp-uglify-es": "^2.0.0",
     "iconv-lite": "^0.5.1",
     "ioredis": "^3.1.4",
     "jszip": "^3.1.3",

BIN
public/static/示例1-分部分项工程项目清单.xlsx


public/static/分部分项工程项目清单计价表.xlsx → public/static/示例2-分部分项工程项目清单计价表.xlsx


+ 2 - 2
public/web/sheet/sheet_common.js

@@ -499,9 +499,9 @@ var sheetCommonObj = {
         return c
     },
     // 无法勾选的复选框
-    getReadOnlyCheckBox () {
+    getReadOnlyCheckBox (threeState = false) {
         function ReadOnlyCheckBox() {}
-        ReadOnlyCheckBox.prototype = new GC.Spread.Sheets.CellTypes.CheckBox();
+        ReadOnlyCheckBox.prototype = this.getCheckBox(threeState);
         ReadOnlyCheckBox.prototype.processMouseUp = function () {
             return;
         };

+ 5 - 2
web/building_saas/complementary_glj_lib/js/glj.js

@@ -297,9 +297,12 @@ let repositoryGljObj = {
             }
         });
         distTypeTree.distTypesArr.forEach(function (distTypeObj) {
-            if (distTypeObj.data.fullName !== '材料' && distTypeObj.data.fullName !== '机械') {
-                distTypeTree.comboDatas.push({ text: distTypeObj.data.fullName, value: distTypeObj.data.ID });
+            if(allowGljType.includes(distTypeObj.data.ID)){
+                distTypeTree.comboDatas.push({text: distTypeObj.data.fullName, value: distTypeObj.data.ID});
             }
+            /* if (distTypeObj.data.fullName !== '材料' && distTypeObj.data.fullName !== '机械') {
+                distTypeTree.comboDatas.push({ text: distTypeObj.data.fullName, value: distTypeObj.data.ID });
+            } */
         });
         return distTypeTree;
     },

+ 9 - 0
web/building_saas/css/custom.css

@@ -518,4 +518,13 @@ margin-right: 100px !important;
 .limit-price-input {
   display: inline-block;
   width: 80px;
+}
+
+.inline-wrapper {
+  display: flex;
+  justify-content: space-between;
+}
+
+.inline-wrapper .inline-tools {
+  display: inline-block;
 }

+ 10 - 5
web/building_saas/main/html/main.html

@@ -100,7 +100,7 @@
                 <a id="importDropDown" class="dropdown-toggle" href="#"><i class="fa fa-cloud-upload"></i></a>
                 <div class="dropdown-menu">
                   <a id="uploadLj" class="dropdown-item" href="#import" data-toggle="modal"
-                    data-target="#import">导入报表Excel清单</a>
+                    data-target="#import">导入Excel清单</a>
                   <a id="uploadGld" class="dropdown-item" href="#import" data-toggle="modal"
                     data-target="#import">导入广联达算量Excel清单</a>
                 </div>
@@ -2014,10 +2014,15 @@
           </div>
           <div id="uploadSheets"></div>
         </div>
-        <div class="modal-footer">
-          <button style="margin-right: 215px;" type="button" class="btn btn-primary" id="uploadExample">下载示例</button>
-          <a href="javascript:void(0);" class="btn btn-primary" id="importConfirm">确定导入</a>
-          <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+        <div class="modal-footer inline-wrapper">
+          <div class="inline-tools">
+            <button type="button" class="btn btn-primary" id="uploadExample-general">下载示例1</button>
+            <button type="button" class="btn btn-primary" id="uploadExample">下载示例2</button>
+          </div>
+          <div class="inline-tools">
+            <a href="javascript:void(0);" class="btn btn-primary" id="importConfirm">确定导入</a>
+            <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+          </div>
         </div>
       </div>
     </div>

+ 6 - 1
web/building_saas/main/js/controllers/block_controller.js

@@ -301,7 +301,7 @@ let BlockController = {
      * @param selected
      * @param position next/pre/sub
      */
-    confirmPaste:function (blockData,selected,position) {
+    confirmPaste:function (blockData,selected,position,callback) {
         let me = this;
         let project = projectObj.project;
         let Bills = project.Bills;
@@ -375,6 +375,11 @@ let BlockController = {
              //主材设备工料机插入主树
              project.ration_glj.addToMainTree(result.ration_gljs);
              //更新计算程序模板,并进行重新计算
+             if(callback){
+                callback(rationNodes,calcNodes);
+                return;
+            }
+
              project.calcProgram.calcNodesAndSave(calcNodes,async function () {
                  installationFeeObj.calcInstallationFee();
                  await OVER_HEIGHT.reCalcOverHeightFee();

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

@@ -1037,7 +1037,7 @@ let calcTools = {
         const totalFee = this.getFee(node, feeField);
         const maxPrice = node.data.maxPrice;
         // 最高限价有值才对比
-        if (!commonUtil.isDef(maxPrice)) {
+        if (!commonUtil.isNumber(maxPrice)) {
             return false;
         }
         return totalFee > maxPrice;
@@ -1050,7 +1050,7 @@ let calcTools = {
         const totalFee = this.getFee(node, feeField);
         const minPrice = node.data.minPrice;
         // 最低限价有值才对比
-        if (!commonUtil.isDef(minPrice)) {
+        if (!commonUtil.isNumber(minPrice)) {
             return false;
         }
         return totalFee < minPrice;

+ 29 - 24
web/building_saas/main/js/views/block_lib.js

@@ -588,30 +588,35 @@ var blockLibObj = {
         $("#div_cloneOptions").modal({show: true});
     },
     oneToOneClone: function (projectNode, block, options) {
-        let canClone = true;
-        if (options.checkCode)
-            canClone = canClone && (projectNode.data.code.substr(0, 9) == block.data.code.substr(0, 9));
-        if (options.checkName)
-            canClone = canClone && (projectNode.data.name == block.data.name);
-        if (options.checkUnit)
-            canClone = canClone && (projectNode.data.unit == block.data.unit);
-        if (!canClone) return;
-        
-        if (options.overwriteRations)
-            projectObj.project.Bills.deleteChildren(projectNode);
-        /*  这里封装成伟城的块文件格式,可直接使用伟城的“粘贴块”接口。
-            但这里结构要作出调整:忽略叶子清单层,直接从定额开始(跟粘贴块有区别),始终强制在叶子清单下插入定额。
-            该操作前提:当前块文件的全部数据已从后台取到前台。  */
-        let vBlock_WC = {
-            compilationID: block.data.compilationID,
-            copyTime: block.data.copyTime,
-            firstNodeType: 1,           // 强制改成1 (因为是从清单下的定额开始。清单自身的还是保留,暂不使用使用)。
-            isFBFX: block.data.isFBFX,
-            zeroQuantity: options.zeroQuantity,
-            datas: block.data.children       // rations
-        };
-        vBlock_WC = JSON.parse(JSON.stringify(vBlock_WC));
-        BlockController.confirmPaste(vBlock_WC, projectNode, 'sub');
+        return new Promise(function (resolve, reject) {        
+            let canClone = true;
+            if (options.checkCode)
+                canClone = canClone && (projectNode.data.code.substr(0, 9) == block.data.code.substr(0, 9));
+            if (options.checkName)
+                canClone = canClone && (projectNode.data.name == block.data.name);
+            if (options.checkUnit)
+                canClone = canClone && (projectNode.data.unit == block.data.unit);
+            if (!canClone) return resolve([[], []]);
+            
+            if (options.overwriteRations)
+                projectObj.project.Bills.deleteChildren(projectNode);
+            /*  这里封装成伟城的块文件格式,可直接使用伟城的“粘贴块”接口。
+                但这里结构要作出调整:忽略叶子清单层,直接从定额开始(跟粘贴块有区别),始终强制在叶子清单下插入定额。
+                该操作前提:当前块文件的全部数据已从后台取到前台。  */
+            let vBlock_WC = {
+                compilationID: block.data.compilationID,
+                copyTime: block.data.copyTime,
+                firstNodeType: 1,           // 强制改成1 (因为是从清单下的定额开始。清单自身的还是保留,暂不使用使用)。
+                isFBFX: block.data.isFBFX,
+                zeroQuantity: options.zeroQuantity,
+                datas: block.data.children       // rations
+            };
+            vBlock_WC = JSON.parse(JSON.stringify(vBlock_WC));
+            BlockController.confirmPaste(vBlock_WC, projectNode, 'sub',function(r, c){
+                resolve([r, c])
+            });
+        })
+
     },
     checkShow: async function () {   // 这里需要处理异步:模板库装载完再弹出位置选择窗。
         if (!$("#kmbk").is(":visible")){  // 如果还没显示

+ 173 - 14
web/building_saas/main/js/views/importBills.js

@@ -50,10 +50,13 @@ const importBills = (function(){
 
     //上传类型
     const uploadType = {
+        general: 'general',
         lj: 'lj',
         gld: 'gld',
     };
 
+    let curFileType = uploadType.general;
+
     //设置导入表内容(选择导入位置)
     //@param {Object}workBook
     function setImportSheetsInfo(sheets){
@@ -131,14 +134,14 @@ const importBills = (function(){
     }
 
     //提取excel表头列名与列下标映射
-    //@
     function getColMapping(dataTable){
         //获取表头
         function getHeadRow(dataTable){
+            const headTexts = [colText.serialNo[0], ...colText.code];
             for(let rowIdx in dataTable ){
                 for(let colIdx in dataTable[rowIdx]){
                     let cellData = dataTable[rowIdx][colIdx]['value'];
-                    if(cellData && _deESC(cellData) === colText.serialNo[0]){
+                    if(cellData && headTexts.includes(_deESC(cellData))){
                         return dataTable[rowIdx];
                     }
                 }
@@ -194,8 +197,16 @@ const importBills = (function(){
         return colMapping;
     }
 
+    // 根据列设置判断从excel表上传界面,上传的具体类型是什么:自定义通用表和09表使用了同一个按钮,因此在获取列设置的时候,还要再区分general和lj
+    function getExactlyFileType(colMapping) {
+        // 只需要区分自定义通用表和09表
+        return !_isDef(colMapping.serialNo) && !_isDef(colMapping.money)
+            ? uploadType.general
+            : uploadType.lj;
+    }
+
     //是否是有效的表头列格式,只要含有各表需要的列就行,不严格控制多少列
-    function isValidSheet(colMapping, fileType){
+    function isValidSheet(colMapping){
         function hasField(field, all){
             for(let i of all){
                 if(field === i){
@@ -205,11 +216,13 @@ const importBills = (function(){
             return false;
         }
         let needFields;
-        if(fileType === uploadType.lj){
+        if (curFileType === uploadType.general) {
+            // 自定义通用表:项目编码	项目名称	项目特征	计量单位	工程量
+            needFields = ['code', 'name', 'itemCharacterText', 'unit', 'quantity'];
+        } else if(curFileType === uploadType.lj){
             //09表:序号、项目编码、项目名称、项目特征、计量单位、工程量、金额
             needFields = ['serialNo', 'code', 'name', 'money'];
-        }
-        else {
+        } else {
             //广联达表:序号、项目编码、项目名称、项目特征、计量单位、工程量、工程量明细、费用明细
             needFields = ['serialNo', 'code', 'name', 'itemCharacterText', 'unit', 'quantity', 'quantityDetail', 'feeDetail'];
         }
@@ -225,8 +238,9 @@ const importBills = (function(){
     //获取要无效和有效导入表
     //@param {Array}importSheetInfo 勾选要导入的表
     function getImportSheets(sheets, sheetsInfo, fileType){
+        curFileType = fileType; // 自定义通用表和09表使用了同一个按钮,因此在获取列设置的时候,还要再区分general和lj
+        let isGetType = false;
         let rst = {invalidSheets: [], validSheets: {fbfx: [], jscsxm: [], zzcsxm: []}};
-
         for(let sheetInfo of sheetsInfo){
             let sheet = getSheetByIndex(sheets, sheetInfo.index);
             if(!sheet){
@@ -237,12 +251,17 @@ const importBills = (function(){
                 rst.invalidSheets.push(sheet.name);
                 continue;
             }
-            //获取表的列设置确定导入的格式是否合法(09、广联达)
+            //获取表的列设置确定导入的格式是否合法(通用excel、09、广联达)
             let colMapping = getColMapping(sheet.data.dataTable);
-            if(!isValidSheet(colMapping, fileType)){
+            // 以第一个有效的sheet作为类型基准
+            if (!isGetType && fileType === uploadType.lj) {
+                curFileType = getExactlyFileType(colMapping);
+            }
+            if(!isValidSheet(colMapping)){
                 rst.invalidSheets.push(sheet.name);
                 continue;
             }
+            isGetType = true;
             //合法的表
             sheet.colMapping = colMapping;
             //将合法的表按导入位置分类当做一个表来处理
@@ -269,7 +288,9 @@ const importBills = (function(){
         let withingD = false;
         let validData = [];
         function isHead(rData){
-            return rData[colMapping.serialNo] && _deESC(rData[colMapping.serialNo]['value']) === colText.serialNo[0];
+            return curFileType === uploadType.general
+                ? rData[colMapping.code] && colText.code.includes(_deESC(rData[colMapping.code]['value']))
+                : rData[colMapping.serialNo] && _deESC(rData[colMapping.serialNo]['value']) === colText.serialNo[0];
         }
         function isTail(rowData){
             for(let colIdx in rowData){
@@ -306,6 +327,147 @@ const importBills = (function(){
         let preRootID = -1,
             preLeafID = -1,
             preID = -1;
+        //父节点
+        function isRoot(rData){
+            //序号和编码去除转义字符(有的表格单元格看起来是没数据,实际含有\r,\n等数据)
+            const code = rData[colMapping.code] ? _deESC(rData[colMapping.code]['value']) : '';
+            const unit = rData[colMapping.unit] ? _deESC(rData[colMapping.unit]['value']) : '';
+            if (curFileType === uploadType.general) {
+                // 通用表:项目编码非12位或者无单位的
+                return !_isDef(code) || !/\w{12}/.test(code) || !_isDef(unit);
+            } else {
+                // 09、广联达表:1.无序号 2有编码
+                const serialNo = rData[colMapping.serialNo] ? _deESC(rData[colMapping.serialNo]['value']) : '';
+                return !_isDef(serialNo) && _isDef(code);
+            }
+        }
+        //子节点
+        function isLeaf(rData){
+            if (curFileType === uploadType.general) {
+                // 通用表:项目编码12位且有单位的
+                const code = rData[colMapping.code] ? _deESC(rData[colMapping.code]['value']) : '';
+                const unit = rData[colMapping.unit] ? _deESC(rData[colMapping.unit]['value']) : '';
+                return _isDef(code) && /\w{12}/.test(code) && _isDef(unit);
+            } else {
+                // 09、广联达表:有序号
+                const serialNo = rData[colMapping.serialNo] ? _deESC(rData[colMapping.serialNo]['value']) : '';
+                return _isDef(serialNo);
+            }
+        }
+        //续数据:1. 前数据有效 2.无序号 3.无编码 4.有名称或特征
+        function isExtend(preData, rData){
+            if (curFileType === uploadType.general) {
+                // 通用表:1. 前数据有效 2.无编码 3.无单位 4.有名称或特征
+                let code = rData[colMapping.code] ? _deESC(rData[colMapping.code]['value']) : '';
+                let unit = rData[colMapping.unit] ? _deESC(rData[colMapping.unit]['value']) : '';
+                let name = rData[colMapping.name] ? _deESC(rData[colMapping.name]['value']) : '';
+                let itemCharacterText = rData[colMapping.itemCharacterText] ? _deESC(rData[colMapping.itemCharacterText]['value']) : '';
+                return _isDef(preData) && (isRoot(preData) || isLeaf(preData)) && !_isDef(unit) && !_isDef(code) && (_isDef(name) || _isDef(itemCharacterText));
+            } else {
+                // 09、广联达表:1. 前数据有效 2.无序号 3.无编码 4.有名称或特征
+                let serialNo = rData[colMapping.serialNo] ? _deESC(rData[colMapping.serialNo]['value']) : '';
+                let code = rData[colMapping.code] ? _deESC(rData[colMapping.code]['value']) : '';
+                let name = rData[colMapping.name] ? _deESC(rData[colMapping.name]['value']) : '';
+                let itemCharacterText = rData[colMapping.itemCharacterText] ? _deESC(rData[colMapping.itemCharacterText]['value']) : '';
+                return _isDef(preData) && (isRoot(preData) || isLeaf(preData)) && !_isDef(serialNo) && !_isDef(code) && (_isDef(name) || _isDef(itemCharacterText));
+            }
+        }
+        function getBillType(rData, flag){
+            if(flag === fixedFlag.CONSTRUCTION_TECH || flag === fixedFlag.CONSTRUCTION_ORGANIZATION){
+                return billType.BILL;
+            }
+            else if(flag === fixedFlag.SUB_ENGINERRING){
+                return isLeaf(rData) ? billType.FX : billType.FB;
+            }
+            return null;
+        }
+        let preData = null;
+        for(let r = 0; r < validData.length; r++){
+            let rData = validData[r];
+            if(flag == fixedFlag.CONSTRUCTION_TECH && rData[colMapping.name] && rData[colMapping.name]['value'] === '施工技术措施项目'
+                || flag == fixedFlag.CONSTRUCTION_ORGANIZATION && rData[colMapping.name] && rData[colMapping.name]['value'] === '施工组织措施项目'){
+                continue;
+            }
+            //过滤无效数据
+            if(!isRoot(rData) && !isLeaf(rData) && !isExtend(preData, rData)){
+                continue;
+            }
+            if(isExtend(preData, rData)){
+                let preBill = billIdx[preID];
+                if(preBill){
+                    //合并续数据
+                    preBill.code += rData[colMapping.code] && rData[colMapping.code]['value'] && _isDef(_deESC(rData[colMapping.code]['value'])) ? rData[colMapping.code]['value'] : '';
+                    preBill.name += rData[colMapping.name] && rData[colMapping.name]['value'] && _isDef(_deESC(rData[colMapping.name]['value'])) ? rData[colMapping.name]['value'] : '';
+                    preBill.itemCharacterText += rData[colMapping.itemCharacterText] && rData[colMapping.itemCharacterText]['value'] && _isDef(_deESC(rData[colMapping.itemCharacterText]['value']))
+                        ? '\n' + _deNR(rData[colMapping.itemCharacterText]['value']) : '';
+                    preBill.unit += rData[colMapping.unit] && rData[colMapping.unit]['value'] && _isDef(_deESC(rData[colMapping.unit]['value'])) ? rData[colMapping.unit]['value'] : '';
+                    preBill.quantity += rData[colMapping.quantity] && rData[colMapping.quantity]['value'] && _isDef(_deESC(rData[colMapping.quantity]['value'])) ? rData[colMapping.quantity]['value'] : '';
+                }
+            } else {
+                let newID = uuid.v1();
+                let pID = -1;
+                let preBill = null;
+                let preRoot = null,
+                    preLeaf = null;
+                let nodeType = 'root';//后端以此标记来设置ParentID
+                let preSerialBill = billIdx[preID];
+                if(isRoot(rData)){
+                    //pID = 'fixedBillID';
+                    preBill = billIdx[preRootID];
+                    preRoot = billIdx[preRootID];
+                } else if(isLeaf(rData)){
+                    nodeType = 'leaf';
+                    //pID = preRootID !== -1 ? preRootID : fixedBill.ID;
+                    preBill = billIdx[preLeafID];
+                    preLeaf = billIdx[preLeafID];
+                }
+                //set bill data
+                billIdx[newID] = {
+                    nodeType: nodeType,
+                    ID: newID, ParentID: pID, NextSiblingID: -1,
+                    code: rData[colMapping.code] && rData[colMapping.code]['value'] ? _deESC(rData[colMapping.code]['value']) : '',
+                    name: rData[colMapping.name] && rData[colMapping.name]['value'] ? _deESC(rData[colMapping.name]['value']) : '',
+                    itemCharacterText: rData[colMapping.itemCharacterText] && rData[colMapping.itemCharacterText]['value'] ? _deNR(rData[colMapping.itemCharacterText]['value']) : '',
+                    itemCharacter: [],
+                    jobContentText: '',
+                    jobContent: [],
+                    programID: null,
+                    unit: rData[colMapping.unit] && rData[colMapping.unit]['value'] ? _deESC(rData[colMapping.unit]['value']) : '',
+                    quantity: rData[colMapping.quantity] && rData[colMapping.quantity]['value'] ? _deESC(rData[colMapping.quantity]['value']) : '',
+                    quantityEXP: rData[colMapping.quantity] && rData[colMapping.quantity]['value'] ? _deESC(rData[colMapping.quantity]['value']) : '',
+                    //安全文明
+                    flags: flag === fixedFlag.CONSTRUCTION_ORGANIZATION && (rData[colMapping.name] && (rData[colMapping.name]['value'] === '安全文明施工专项费用' || rData[colMapping.name]['value'] === '安全文明施工费')) ?
+                        [{fieldName: 'fixed', flag: fixedFlag.SAFETY_CONSTRUCTION}] : [],
+                    fees: [],
+                    projectID: projectID,
+                    type: getBillType(rData, flag)};
+                //update preBill NextSibling
+                if(nodeType === 'root' && preRoot){
+                    preRoot.NextSiblingID = newID;
+                } else if(nodeType === 'leaf' && preLeaf && preSerialBill && preSerialBill.nodeType === preLeaf.nodeType){
+                    preLeaf.NextSiblingID = newID;
+                }
+               /* if(preBill){
+                    preBill.NextSiblingID = newID;
+                }*/
+                //set new preID
+                preID = newID;
+                preRootID = isRoot(rData) ? newID : preRootID;
+                preLeafID = isLeaf(rData) ? newID : preLeafID;
+            }
+            preData = rData;
+        }
+        for(let i in billIdx){
+            rst.push(billIdx[i]);
+        }
+        return rst;
+    }
+    /* function parseToBillData(validData, colMapping, flag, projectID){
+        let rst = [];
+        let billIdx = {};
+        let preRootID = -1,
+            preLeafID = -1,
+            preID = -1;
         //父节点:1.无序号 2有编码
         function isRoot(rData){
             //序号和编码去除转义字符(有的表格单元格看起来是没数据,实际含有\r,\n等数据)
@@ -404,9 +566,6 @@ const importBills = (function(){
                 else if(nodeType === 'leaf' && preLeaf && preSerialBill && preSerialBill.nodeType === preLeaf.nodeType){
                     preLeaf.NextSiblingID = newID;
                 }
-               /* if(preBill){
-                    preBill.NextSiblingID = newID;
-                }*/
                 //set new preID
                 preID = newID;
                 preRootID = isRoot(rData) ? newID : preRootID;
@@ -418,7 +577,7 @@ const importBills = (function(){
             rst.push(billIdx[i]);
         }
         return rst;
-    }
+    } */
 
     function getImportData(validSheets, projectID){
         let rst = {fbfx: [], jscsxm: [], zzcsxm: []};

+ 4 - 4
web/building_saas/main/js/views/main_tree_col.js

@@ -460,16 +460,16 @@ let MainTreeCol = {
         },
         outPutMaxPrice:function (node) {
             if(MainTreeCol.mainBillsEnable(node)) {
-                return projectObj.project.projectInfo.importedByInterface
+                return projectObj.project.projectInfo.importedByInterface || projectObj.project.projectInfo.property.lockBills
                     ? sheetCommonObj.getReadOnlyCheckBox()
-                    : sheetCommonObj.getCheckBox(true);
+                    : sheetCommonObj.getCheckBox();
             }
         },
         outPutLimitPrice:function (node) {
             if(MainTreeCol.mainBillsEnable(node)) {
-                return projectObj.project.projectInfo.importedByInterface
+                return projectObj.project.projectInfo.importedByInterface || projectObj.project.projectInfo.property.lockBills
                 ? sheetCommonObj.getReadOnlyCheckBox()
-                : sheetCommonObj.getCheckBox(true);
+                : sheetCommonObj.getCheckBox();
             }
         },
         overHeight: function (node) {

+ 33 - 9
web/building_saas/main/js/views/project_view.js

@@ -550,7 +550,7 @@ var projectObj = {
                 project.calcProgram.calcAndSave(node);
             } else {
                 if (node.sourceType === project.Bills.getSourceType()) {
-                    if(fieldName == "maxPrice"){
+                    if(fieldName === "maxPrice" || fieldName === 'minPrice'){
                         if(value == null){
                             value = "";
                         }else {
@@ -3075,14 +3075,18 @@ function canInsertRationNode(selected) {//判断是否能插入定额、量价
 }
 
 //导入类型(09表、广联达)
-const uploadType = {lj: 'lj', gld: 'gld'};
+const uploadType = {general: 'general', lj: 'lj', gld: 'gld'};
 let fileType = uploadType.lj;
 
 $('#uploadLj').click(function () {
+    $('#uploadExample-general').show();
+    $('#uploadExample').text('下载示例2');
     fileType = uploadType.lj;
 });
 $('#uploadGld').click(function () {
-   fileType = uploadType.gld;
+    $('#uploadExample-general').hide();
+    $('#uploadExample').text('下载示例');
+    fileType = uploadType.gld;
 });
 
 let importJson = null;
@@ -3196,6 +3200,7 @@ $('#importConfirm').click(function () {
         });
     }
     catch (err){
+        console.log(err);
         showUploadAlert(false, err);
         $(me).removeClass('disabled');
         if($.bootstrapLoading.isLoading()){
@@ -3318,8 +3323,11 @@ function doAfterImport(resData){
     }
 }
 //下载导入清单示例文件
+$('#uploadExample-general').click(function () {
+    window.location.href = `/bills/downloadExamp?type=${uploadType.general}`;
+});
 $('#uploadExample').click(function () {
-    window.location.href = `/bills/downloadExamp?type=${fileType}`;
+    window.location.href = `/bills/downloadExamp?type=${fileType === uploadType.lj ? uploadType.lj : uploadType.gld}`;
 });
 
 $(function () {
@@ -3449,7 +3457,7 @@ $(function () {
         $("#div_createBlocks").modal("hide");
     });
 
-    $("#btn_block_clone_ok").click(function () {
+    $("#btn_block_clone_ok").click(async function () {
         let projectNode = projectObj.project.mainTree.selected;
         let block = blockLibObj.mainTree.selected;
         let options = {};
@@ -3458,16 +3466,20 @@ $(function () {
         if ($('#clone_option_unit').prop("checked")) options.checkUnit = true;
         if ($('#clone_option_zeroQuantity').prop("checked")) options.zeroQuantity = true;
         if ($('#clone_option_cover').prop("checked")) options.overwriteRations = true;
-
+        
+        let nodes = [];
+        let calcNodes = [];
         switch (blockLibObj.cloneType) {
             case 1:
-                blockLibObj.oneToOneClone(projectNode, block, options);
+                nodes = await blockLibObj.oneToOneClone(projectNode, block, options);
+                calcNodes = calcNodes.concat(nodes[1]);
                 break;
             case 2:
                 let bills = calcTools.getLeafBills(projectNode);
                 for (let bill of bills){
                     calcTools.forceSelect(bill);
-                    blockLibObj.oneToOneClone(bill, block, options);
+                    nodes = await blockLibObj.oneToOneClone(bill, block, options);
+                    calcNodes = calcNodes.concat(nodes[1]);
                 };
                 break;
             case 3:
@@ -3476,11 +3488,23 @@ $(function () {
                 for (let mtmBill of mtmBills){
                     for (let mtmBlock of mtmBlocks){
                         calcTools.forceSelect(mtmBill);
-                        blockLibObj.oneToOneClone(mtmBill, mtmBlock, options);
+                        nodes = await blockLibObj.oneToOneClone(mtmBill, mtmBlock, options);
+                        calcNodes = calcNodes.concat(nodes[1]);
                     };
                 };
                 break;
         }
+        if(calcNodes.length > 0){
+            // projectObj.project.calcProgram.calcNodesAndSave(calcNodes, function () {
+            //     installationFeeObj.calcInstallationFee();
+            // });
+
+            projectObj.project.calcProgram.calcNodesAndSave(calcNodes, async function () {
+                installationFeeObj.calcInstallationFee();
+                await OVER_HEIGHT.reCalcOverHeightFee();
+                await itemIncreaseFeeObj.calcItemIncreaseFeeByNodes(nodes[0]);
+            });
+        }
     });
 
 

+ 30 - 0
web/over_write/js/guangdong_2018.js

@@ -9,6 +9,36 @@
  */
 let isGD2018 = true;
 
+//允许使用的工料机类型:人工、普通材料、其他材料费、混凝土、砂浆、配合比、商品混凝土、商品砂浆
+//机械台班、机上人工、机械组成物、主材、设备、企业管理费
+if(typeof allowGljType !== 'undefined'){
+    allowGljType = [1, 201, 202, 203, 204, 205, 206, 207, 301, 302, 303, 4,5, 6];
+}
+if(typeof allowComponent !== 'undefined'){
+    //允许含有组成物的工料机类型:混凝土、砂浆、配合比、机械台班、主材
+    allowComponent = [202, 203, 204, 301, 4];
+}
+if(typeof componentType !== 'undefined'){
+    //可以作为组成物的工料机类型:普通材料、机械组成物、机上人工、主材
+    componentType = [201, 302, 303, 4];
+}
+if(typeof machineAllowComponent !== 'undefined'){
+    //允许含有组成物的机械工料机类型:机械台班器仪表
+    machineAllowComponent = [301];
+}
+if(typeof machineComponent !== 'undefined'){
+    //可以作为机械工料机组成物的工料机类型:机械组成物、机上人工
+    machineComponent = [302, 303];
+}
+if(typeof materialAllowComponent !== 'undefined'){
+    //允许含有组成物的材料工料机类型:混凝土、砂浆、配合比
+    materialAllowComponent = [202, 203, 204];
+}
+if(typeof materialComponent !== 'undefined'){
+    //可以作为材料工料机组成物的工料机类型:普通材料
+    materialComponent = [201];
+}
+
 function overwriteRationCalcBases (){
     if (typeof rationCalcBases == 'undefined') return;
     for (let key in rationCalcBases) delete rationCalcBases[key];

+ 30 - 0
web/over_write/js/jiangxi_2017.js

@@ -4,6 +4,36 @@
 
 let isJX2017 = true;
 
+//允许使用的工料机类型:人工、普通材料、其他材料费、混凝土、砂浆、配合比、商品混凝土、商品砂浆
+//机械台班、机上人工、机械组成物、主材、设备
+if(typeof allowGljType !== 'undefined'){
+    allowGljType = [1, 201, 202, 203, 204, 205, 206, 207, 301, 302, 303, 4, 5];
+}
+if(typeof allowComponent !== 'undefined'){
+    //允许含有组成物的工料机类型:混凝土、砂浆、配合比、机械台班、主材
+    allowComponent = [202, 203, 204, 301, 4];
+}
+if(typeof componentType !== 'undefined'){
+    //可以作为组成物的工料机类型:普通材料、机械组成物、机上人工、主材
+    componentType = [201, 302, 303, 4];
+}
+if(typeof machineAllowComponent !== 'undefined'){
+    //允许含有组成物的机械工料机类型:机械台班器仪表
+    machineAllowComponent = [301];
+}
+if(typeof machineComponent !== 'undefined'){
+    //可以作为机械工料机组成物的工料机类型:机械组成物、机上人工
+    machineComponent = [302, 303];
+}
+if(typeof materialAllowComponent !== 'undefined'){
+    //允许含有组成物的材料工料机类型:混凝土、砂浆、配合比
+    materialAllowComponent = [202, 203, 204];
+}
+if(typeof materialComponent !== 'undefined'){
+    //可以作为材料工料机组成物的工料机类型:普通材料
+    materialComponent = [201];
+}
+
 // 一般计税取不含税市场价、不含税定额价。简易计税取含税市场价、含税定额价。打开项目时,4个价格根据计税类型只载入其二,所以这里可不作区分。
 function overwriteRationCalcBases (taxType){
     if (typeof rationCalcBases == 'undefined') return;

+ 29 - 0
web/over_write/js/neimenggu_2017.js

@@ -2,6 +2,35 @@
 
 // CSL, 2019-01-18
 
+//允许使用的工料机类型:人工、普通材料、混凝土、砂浆、配合比、商品混凝土、商品砂浆、其他材料费、机械台班、机械组成物、机上人工、主材、设备、企业管理费、利润
+if(typeof allowGljType !== 'undefined'){
+    allowGljType = [1, 201, 202, 203, 204, 205, 206, 207, 301, 302, 303, 4, 5, 6, 7];
+}
+if(typeof allowComponent !== 'undefined'){
+    //允许含有组成物的工料机类型:混凝土、砂浆、配合比、机械台班、主材
+    allowComponent = [202, 203, 204, 301, 4];
+}
+if(typeof componentType !== 'undefined'){
+    //可以作为组成物的工料机类型:普通材料、机械组成物、机上人工、主材
+    componentType = [201, 302, 303, 4];
+}
+if(typeof machineAllowComponent !== 'undefined'){
+    //允许含有组成物的机械工料机类型:机械台班
+    machineAllowComponent = [301];
+}
+if(typeof machineComponent !== 'undefined'){
+    //可以作为机械工料机组成物的工料机类型:机械组成物、机上人工
+    machineComponent = [302, 303];
+}
+if(typeof materialAllowComponent !== 'undefined'){
+    //允许含有组成物的材料工料机类型:混凝土、砂浆、配合比
+    materialAllowComponent = [202, 203, 204];
+}
+if(typeof materialComponent !== 'undefined'){
+    //可以作为材料工料机组成物的工料机类型:普通材料
+    materialComponent = [201];
+}
+
 (function overwriteFeeTypes() {
     if (typeof cpFeeTypes == 'undefined') return;
     cpFeeTypes = [