Selaa lähdekoodia

Merge branch 'master' of http://smartcost.f3322.net:3000/SmartCost/ConstructionCost

zhongzewei 7 vuotta sitten
vanhempi
commit
6550b42a9a

+ 8 - 7
modules/bills_lib/models/bills_lib_interfaces.js

@@ -3057,14 +3057,15 @@ billsLibDao.prototype.getStdBillsByCode = async function (data, callback) {
     }
     try{
         let bills = await Bills.findOne({billsLibId: data.billsLibId, code: data.code, deleted: false}, '-_id');
-        //设置清单备注(父项清单补注)
-        if(bills.ParentID != -1){
-            let parentBills = await Bills.findOne({billsLibId: data.billsLibId, ID: bills.ParentID, deleted: false});
-            if(parentBills && parentBills.recharge){
-                bills.recharge = parentBills.recharge;
-            }
-        }
+
         if(bills){
+            //设置清单备注(父项清单补注)
+            if(bills.ParentID != -1){
+                let parentBills = await Bills.findOne({billsLibId: data.billsLibId, ID: bills.ParentID, deleted: false});
+                if(parentBills && parentBills.recharge){
+                    bills.recharge = parentBills.recharge;
+                }
+            }
             //设置项目特征
             let itemCharacters = await ItemCharacter.find({billsLibId: data.billsLibId, deleted: false}, '-_id');
             bills._doc.itemCharacter = [];

+ 28 - 0
modules/glj/controllers/glj_controller.js

@@ -660,6 +660,33 @@ class GLJController extends BaseController {
         }
         res.json(result);
     }
+    async batchUpdateGLJProperty(req, res){
+        let result={
+            error:0
+        };
+        try {
+            let data = req.body.data;
+            data = JSON.parse(data);
+            let tasks = [];
+            for(let key in data){
+                let doc = data[key];
+                let query = {id:parseInt(key)};
+                let task = {updateOne:{filter:query, update :doc}};
+                tasks.push(task);
+            }
+            if(tasks.length > 0){
+                let gljModel = new GLJListModel().model;
+                await gljModel.bulkWrite(tasks);
+            }
+            result.data=data;
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        res.json(result);
+    }
+
     async batchUpdateConsumption(req,res){
         let result={
             error:0
@@ -707,6 +734,7 @@ class GLJController extends BaseController {
         }
         res.json(result);
     }
+
     async modifyKeyValue(req,res){//修改工料机关键的属性:名称、类型、规格、型号等
         let result={
             error:0

+ 1 - 0
modules/glj/routes/glj_router.js

@@ -25,6 +25,7 @@ router.post('/save-as', gljController.init, gljController.unitPriceSaveAs);
 router.post('/get-composition', gljController.init, gljController.getComposition);
 router.post('/updatePrice', gljController.init, gljController.updateUnitPrice);
 router.post('/batchUpdatePrices', gljController.init, gljController.batchUpdatePrices);
+router.post('/batchUpdateGLJProperty', gljController.init, gljController.batchUpdateGLJProperty);
 router.post('/batchUpdateConsumption', gljController.init, gljController.batchUpdateConsumption);
 router.post('/modifyKeyValue',gljController.init, gljController.modifyKeyValue);
 

+ 13 - 5
public/scHintBox.html

@@ -38,6 +38,11 @@
     const hintBox = {
         value: null,
         btnType: {yes: 1, yesNo: 2, yesNoCancel: 3},
+        defalultEvent: function () {
+            $.bootstrapLoading.end();
+//            alert('defalultEvent');
+            return;
+        },
         init: function (){
             // 事件类
             $("#hintBox_value").unbind();
@@ -55,10 +60,7 @@
                 }
             );
             $('#hintBox_btn_cancel').click(
-                function () {
-                    $.bootstrapLoading.end();
-                    return;
-                }
+                hintBox.defalultEvent
             );
 
             // 显示类
@@ -79,7 +81,9 @@
             $("#hintBox_value").focus();
             $("#hintBox_value").select();
         },
-        infoBox: function (title, caption, btnType, doYes, doNo, btnTextArr, showCrossBtn = true) {
+        infoBox: function (title, caption, btnType,
+                           doYes, doNo = hintBox.defalultEvent,
+                           btnTextArr = null, showCrossBtn = true) {
             this.init();
             if (!showCrossBtn)
                 $('#hintBox_btn_cross').hide();
@@ -149,6 +153,10 @@
             $('#hintBox_btn_yes').show();
             $('#hintBox_btn_yes').click(doOK);   // doOK不能给参数
 
+            $('#hintBox_btn_no').text('取消');
+            $('#hintBox_btn_no').show();
+            $('#hintBox_btn_no').click(hintBox.defalultEvent);
+
             $("#hintBox_form").modal('show');
         }
     };

+ 2 - 1
public/web/sheet/sheet_data_helper.js

@@ -55,8 +55,9 @@ var SheetDataHelper = {
         spread.options.allowContextMenu = false;
         spread.options.allowUserDragDrop = false;
         spread.options.allowUndo = false;//that.mainSpread.commandManager().setShortcutKey(undefined, GC.Spread.Commands.Key.z, true, false, false, false); 屏蔽undo
-        spread.options. allowUserEditFormula = false;
+        spread.options.allowUserEditFormula = false;
         spread.options.showDragFillSmartTag = false;
+        spread.options.defaultDragFillType =GC.Spread.Sheets.Fill.AutoFillType.fillWithoutFormatting;
         spread.getActiveSheet().setRowCount(3);
         return spread;
     },

+ 4 - 2
test/public/test_Box.html

@@ -30,11 +30,13 @@
             });
 
             $("#btnB").click(function(){
-                hintBox.infoBox('操作确认', '确定要删除当前节点吗?', 2, cbYes, cbNo);
+                hintBox.infoBox('操作确认', '确定要删除当前节点吗?', 2, cbYes);
+                // 或: hintBox.infoBox('操作确认', '确定要删除当前节点吗?', 2, cbYes, cbNo);
             });
 
             $("#btnC").click(function(){
-                hintBox.infoBox('多分支选择', '三个按钮是否继续?', 3, cbYes, cbNo, ['你','我','他']);
+                hintBox.infoBox('多分支选择', '三个按钮是否继续?', 3, cbYes, cbNo);
+                // 或: hintBox.infoBox('多分支选择', '三个按钮是否继续?', 3, cbYes, undefined, ['你','我','他']);
             });
 
             $("#btnD").click(function(){

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

@@ -899,6 +899,7 @@
                             <button class="btn btn-secondary btn-sm" id="divOpr">/</button>
                             <button class="btn btn-secondary btn-sm" id="leftOpr">(</button>
                             <button class="btn btn-secondary btn-sm" id="rightOpr">)</button>
+                            <span id="errorInfo" style="margin-left:15px;"></span>
                         </p>
                     </div>
                     <div class="row" id="cbRowDiv">
@@ -1218,12 +1219,12 @@
         </div>
     </div>
 
-    <!--弹出 粘位置选择-->
+    <!--弹出 粘位置选择-->
     <div class="modal fade" id="pastePosition" data-backdrop="static">
         <div class="modal-dialog" role="document">
             <div class="modal-content">
                 <div class="modal-header">
-                    <h5 class="modal-title">粘位置选择</h5>
+                    <h5 class="modal-title">粘位置选择</h5>
                     <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                         <span aria-hidden="true">&times;</span>
                     </button>
@@ -1247,9 +1248,9 @@
                         </div>
                     </div>
                 </div>
-                <div class="modal-footer">
+                <div class="modal-footer" style="justify-content: center">
                     <button class="btn btn-primary" id="paste_confirm">确定</button>
-                    <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
                 </div>
             </div>
         </div>

+ 32 - 4
web/building_saas/main/js/models/bills.js

@@ -506,14 +506,42 @@ var Bills = {
                 return false;
             }
         };
-        bills.prototype.isEngineerEst = function (node) {//判断是否是“专业工程暂估价”节点
-            return node && isFlag(node.data)&&node.data.flagsIndex.fixed.flag==fixedFlag.ENGINEERING_ESITIMATE;
+        bills.prototype.nodeFlagCheck = function (node,fixedFlag) {//判断节点类型
+            let flagCheck = function (checkNode) {
+                if(isFlag(checkNode.data)&&checkNode.data.flagsIndex.fixed.flag==fixedFlag){
+                    return true;
+                }else {
+                    if(checkNode.parent){
+                        return flagCheck(checkNode.parent);
+                    }else {
+                        return false;
+                    }
+                }
+            };
+            return flagCheck(node);
+        };
+
+        bills.prototype.getNodeByFlag = function(node,flag){//取节点类型,返回本身或父项节点
+            if(node){
+                if(isFlag(node.data)&&node.data.flagsIndex.fixed.flag==flag){
+                    return node;
+                }else {
+                    return this.getNodeByFlag(node.parent,flag);
+                }
+            }else {
+                return null;
+            }
+        };
+
+        bills.prototype.isEngineerEst = function (node) {//判断是否是“专业工程暂估价”节点或者子项
+           return this.nodeFlagCheck(node,fixedFlag.ENGINEERING_ESITIMATE);
+            //return node && isFlag(node.data)&&node.data.flagsIndex.fixed.flag==fixedFlag.ENGINEERING_ESITIMATE;
         };
         bills.prototype.isTotalService = function (node) {//判断是否是“总承包服务费”节点
-            return node && isFlag(node.data)&&node.data.flagsIndex.fixed.flag==fixedFlag.TURN_KEY_CONTRACT;
+            return this.nodeFlagCheck(node,fixedFlag.TURN_KEY_CONTRACT);
         };
         bills.prototype.isClaimVisa = function (node) {//判断是否是“签证及索赔计价”节点
-            return node && isFlag(node.data)&&node.data.flagsIndex.fixed.flag==fixedFlag.CLAIM_VISA;
+            return this.nodeFlagCheck(node,fixedFlag.CLAIM_VISA);
         };
         bills.prototype.isMeasure = function (node) {//判读是否属于措施项目部分
             let rootNode = this.getRootNode(node);

+ 56 - 20
web/building_saas/main/js/models/calc_program.js

@@ -707,10 +707,14 @@ let calcTools = {
         glj.tenderQuantity = (glj.quantity * qCoe).toDecimal(decimalObj.glj.quantity);
     },
     calcGLJTenderPrice: function (glj) {
-        let pCoe = 1;
-        if (projectObj.project.property.tenderSetting && projectObj.project.property.tenderSetting.gljPriceTenderCoe)
-            pCoe = projectObj.project.property.tenderSetting.gljPriceTenderCoe;
-        glj.tenderPrice = (glj.marketPrice * pCoe).toDecimal(decimalObj.glj.unitPrice);
+        // let pCoe = 1;
+        // if (projectObj.project.property.tenderSetting && projectObj.project.property.tenderSetting.gljPriceTenderCoe)
+        //     pCoe = projectObj.project.property.tenderSetting.gljPriceTenderCoe;
+        // if (compositionTypes.indexOf(glj.type) >= 0)
+        //
+        // else
+        //     glj.tenderPrice = (glj.marketPrice * pCoe).toDecimal(decimalObj.glj.unitPrice);
+        glj.tenderPrice = projectObj.project.projectGLJ.getTenderMarketPrice(projectObj.project.projectGLJ.getDataByID(glj.projectGLJID));
     },
     // 界面显示的工料机价格,包括定额价、市场价等。参数 price 传入一个普通的价格数值即可。
     uiGLJPrice: function (price){
@@ -728,8 +732,14 @@ let calcTools = {
     getRationsByProjectGLJ(PGLJID){
         let rationIDs = [];
         let RGs = projectObj.project.ration_glj.datas;
+        let PGLJIDs = [];
+        if(Array.isArray(PGLJID)){//为了提高效率,改成支持传入数组
+            PGLJIDs = PGLJID
+        }else {
+            PGLJIDs = [PGLJID];
+        }
         for (let rg of RGs){
-            if (rg.projectGLJID == PGLJID){
+            if (PGLJIDs.indexOf(rg.projectGLJID) !== -1){
                 rationIDs.push(rg.rationID);
             }
         };
@@ -743,7 +753,7 @@ let calcTools = {
         // 工料机形式的定额
         let items = projectObj.project.mainTree.items;
         for (let item of items){
-            if (item.data.projectGLJID == PGLJID)
+            if (PGLJIDs.indexOf(item.data.projectGLJID)  !== -1)
                 rationNodes.push(item);
         };
 
@@ -899,6 +909,7 @@ const rationCalcBases = {
 };
 
 let analyzer = {
+    error: '',
     standard: function(expr){
         let str = expr;
         str = str.replace(/\s/g, "");               // 去空格、去中文空格
@@ -975,14 +986,16 @@ let analyzer = {
         let expr = me.standard(dispExpr);
         let invalidChars = /[^0-9\u4e00-\u9fa5\+\-\*\/\(\)\.\[\]FL%]/g;
         if (invalidChars.test(expr)){
-            hintBox.infoBox('错误提示',`表达式中含有${hintBox.font('无效字符')}!`,1);
+            analyzer.error = `表达式中含有${hintBox.font('无效字符')}!`;
+            // hintBox.infoBox('错误提示',`表达式中含有${hintBox.font('无效字符')}!`,1);
             return false;
         };
 
         let i = expr.search(/\df/ig);   // 4F3
         let j = expr.search(/\d\[/ig);  // 4[定额基价人工费]
         if (i > -1 || j > -1){
-            hintBox.infoBox('错误提示', `表达式中${hintBox.font('缺少运算符')}!`, 1);
+            analyzer.error = `表达式中${hintBox.font('缺少运算符')}!`;
+            // hintBox.infoBox('错误提示', `表达式中${hintBox.font('缺少运算符')}!`, 1);
             return false;
         }
 
@@ -991,26 +1004,30 @@ let analyzer = {
         let pattBase = new RegExp(/\[[\u4E00-\u9FA5]+\]/gi);
         let arrBase = expr.match(pattBase);
         if (arrCn && !arrBase){
-            hintBox.infoBox('错误提示', `定额基数必须用中括号${hintBox.font('[]')}括起来!`, 1);
+            analyzer.error = `定额基数必须用中括号${hintBox.font('[]')}括起来!`;
+            // hintBox.infoBox('错误提示', `定额基数必须用中括号${hintBox.font('[]')}括起来!`, 1);
             return false;
         };
         if (arrCn && arrBase && (arrCn.length != arrBase.length)){
             for (let cn of arrCn){
                 let tempBase = `[${cn}]`;
                   if (!arrBase.includes(tempBase)){
-                      hintBox.infoBox('错误提示', `定额基数“${hintBox.font(cn)}”必须用中括号${hintBox.font('[]')}括起来!`, 1);
+                      analyzer.error = `定额基数“${hintBox.font(cn)}”必须用中括号${hintBox.font('[]')}括起来!`;
+                      // hintBox.infoBox('错误提示', `定额基数“${hintBox.font(cn)}”必须用中括号${hintBox.font('[]')}括起来!`, 1);
                       return false;
                   }
             };
             // 这里要加一个保险。因为上面的 for 循环在“主材费 + [主材费]” 情况下有Bug
-            hintBox.infoBox('错误提示', `定额基数必须用中括号${hintBox.font('[]')}括起来!`, 1);
+            analyzer.error =`定额基数必须用中括号${hintBox.font('[]')}括起来!`;
+            // hintBox.infoBox('错误提示', `定额基数必须用中括号${hintBox.font('[]')}括起来!`, 1);
             return false;
         };
         if (arrBase){
             for (let base of arrBase){
                 let baseName = base.slice(1, -1);
                 if (!rationCalcBases[baseName]){
-                    hintBox.infoBox('错误提示', `定额基数${hintBox.font('[' +baseName + ']')}末定义!`, 1);
+                    analyzer.error = `定额基数${hintBox.font('[' +baseName + ']')}末定义!`;
+                    // hintBox.infoBox('错误提示', `定额基数${hintBox.font('[' +baseName + ']')}末定义!`, 1);
                     return false;
                 }
             };
@@ -1021,18 +1038,21 @@ let analyzer = {
             let num = F.slice(1);
             if (num > template.calcItems.length){
                 let s = hintBox.font('F'+num);
-                hintBox.infoBox('错误提示', `表达式中 “${hintBox.font(s)}” 行号引用错误!`, 1);
+                analyzer.error = `表达式中 “${hintBox.font(s)}” 行号引用错误!`;
+                // hintBox.infoBox('错误提示', `表达式中 “${hintBox.font(s)}” 行号引用错误!`, 1);
                 return false;
             };
         };
 
         let expression = me.getExpression(expr, template);
         if (me.isCycleCalc(expression, itemID, template)){
-            hintBox.infoBox('错误提示', `表达式中有${hintBox.font('循环计算')}!`, 1);
+            analyzer.error = `表达式中有${hintBox.font('循环计算')}!`;
+            // hintBox.infoBox('错误提示', `表达式中有${hintBox.font('循环计算')}!`, 1);
             return false;
         };
         if (!testValue(expression)){
-            hintBox.infoBox('错误提示', `表达式中有${hintBox.font('语法错误')}!`, 1);
+            analyzer.error = `表达式中有${hintBox.font('语法错误')}!`;
+            // hintBox.infoBox('错误提示', `表达式中有${hintBox.font('语法错误')}!`, 1);
             return false;
         };
 
@@ -1136,6 +1156,17 @@ let analyzer = {
         }
         return false;
     },
+    refreshUsedCalcItemsStatement: function(template, calcItem){
+        let atID = '@' + calcItem.ID;
+        for (var i = 0; i < template.calcItems.length; i++) {
+            let item = template.calcItems[i];
+            let atIDArr = analyzer.getAtIDArr(item.expression);
+            if (atIDArr.indexOf(atID) >= 0){
+                item.statement = analyzer.getStatement(item.expression, template);
+            };
+        }
+    },
+
     calcItemLabourCoe: function(calcItem){
         let lc = 0;
         if (calcItem.labourCoeID)
@@ -1158,7 +1189,7 @@ let analyzer = {
         return MaxID;
     },
     templateNewName: function (name) {
-        let i = 2;
+        let i = 1;
         while (projectObj.project.calcProgram.compiledTemplateMaps[name + i]) {
             i++;
         };
@@ -1906,9 +1937,11 @@ class CalcProgram {
 
     // 反向调价
     calcTenderReverse(treeNode, tender){
-        if (treeNode.data.feesIndex.common.tenderUnitFee != treeNode.data.feesIndex.common.unitFee){
-            treeNode.data.feesIndex.common.tenderUnitFee = treeNode.data.feesIndex.common.unitFee;
-            treeNode.changed = true;
+        if (tender == tenderTypes.ttReverseRation) {
+            if (treeNode.data.feesIndex.common.tenderUnitFee != treeNode.data.feesIndex.common.unitFee) {
+                treeNode.data.feesIndex.common.tenderUnitFee = treeNode.data.feesIndex.common.unitFee;
+                treeNode.changed = true;
+            }
         };
 
         if (!treeNode.data.targetTotalFee){
@@ -1921,9 +1954,12 @@ class CalcProgram {
             }
         };
 
+        if (!treeNode.data.targetUnitFee)
+            treeNode.data.targetUnitFee = (treeNode.data.targetTotalFee / treeNode.data.quantity).toDecimal(decimalObj.decimal('unitPrice', treeNode));
         let coe = 1;
         if (treeNode.data.feesIndex.common.totalFee != 0)
-            coe = (treeNode.data.targetTotalFee / treeNode.data.feesIndex.common.totalFee).toDecimal(2);//(decimalObj.process);
+            // coe = (treeNode.data.targetTotalFee / treeNode.data.feesIndex.common.totalFee).toDecimal(decimalObj.process);
+            coe = (treeNode.data.targetUnitFee / treeNode.data.feesIndex.common.unitFee).toDecimal(decimalObj.process);
 
         if (tender == tenderTypes.ttReverseRation){
             treeNode.data.tenderQuantity = (treeNode.data.quantity * coe).toDecimal(decimalObj.decimal("quantity", treeNode));

+ 1 - 1
web/building_saas/main/js/models/main_consts.js

@@ -73,7 +73,7 @@ const allMaterialTypes = [
     gljType.MAIN_MATERIAL,
     gljType.EQUIPMENT
 ];
-// 会有组成物的材料
+// 会有组成物的材料、机械台班
 const compositionTypes = [
     gljType.MAIN_MATERIAL,
     gljType.CONCRETE,

+ 110 - 8
web/building_saas/main/js/models/project_glj.js

@@ -298,16 +298,68 @@ ProjectGLJ.prototype.updatePrice = function (recode, updateField, newval,from,cb
     }
 };
 
-ProjectGLJ.prototype.batchUpdatePrice = function (changeInfo,callback) {
+ProjectGLJ.prototype.batchUpdateGLJProperty = function (updateMap,callback) {
+    let me = this;
+    //更新是否暂估和供货方式时,要做特殊处理
+    $.bootstrapLoading.start();
+    CommonAjax.post("/glj/batchUpdateGLJProperty", updateMap,function (result) {
+        $.bootstrapLoading.end();
+        let supplyChangeIDs = [],evaluate_gljs = [],rationNodes = [];
+        console.log(updateMap);
+        for(let idKey in updateMap){
+            let gljID = parseInt(idKey);
+            let glj = me.getByID(gljID);
+            let doc = updateMap[idKey];
+            for(let property in doc){
+                glj[property] = doc[property];
+            }
+            if(doc.hasOwnProperty("supply")||doc.hasOwnProperty("supply_quantity")){
+                supplyChangeIDs.push(gljID);
+            }
+            if(doc.hasOwnProperty("is_evaluate")){
+                evaluate_gljs.push(glj);
+            }
+        }
+        if(supplyChangeIDs.length>0){
+            let temRationNodes = calcTools.getRationsByProjectGLJ(supplyChangeIDs);
+            if (temRationNodes.length > 0) rationNodes = rationNodes.concat(temRationNodes);
+        }
+        if(evaluate_gljs.length > 0){
+            let [impactRationNodes,impactGLJs] = me.batchChangeIsEvaluate(evaluate_gljs);
+            rationNodes = rationNodes.concat(impactRationNodes);
+        }
+
+        if(rationNodes.length > 0){
+            rationNodes = _.uniq(rationNodes,'data');
+            projectObj.project.calcProgram.calcNodesAndSave(rationNodes, function () {
+                projectObj.mainController.refreshTreeNode(projectObj.project.mainTree.roots);
+            });
+        }
+
+        if(callback){
+            callback();
+        }
+
+    })
+
+
+};
+
+ProjectGLJ.prototype.batchUpdatePrice = function (changeInfo,sheetName,callback) {
     let me = this;
     let projectGljs = me.datas.gljList;
     let decimal = getDecimal('glj.unitPrice');
     let updateData = [];
     let newValueMap = {};
     let gljs=[];
+    let setting = sheetName =="materialTreeSheet"?projectGljObject.materialSetting:projectGljObject.projectGljSetting;
+    if(changeInfo.length<=0){
+        callback?callback():'';
+        return
+    }
     for(let ci of changeInfo){
-        let dataCode = projectGljObject.projectGljSetting.header[ci.col].dataCode;
-        let recode = projectGljObject.projectGljSheetData[ci.row];
+        let dataCode = setting.header[ci.col].dataCode;
+        let recode = sheetName =="materialTreeSheet"?projectGljObject.materialTree.items[ci.row].data:projectGljObject.projectGljSheetData[ci.row];
         if(dataCode=='basePrice'||dataCode=='marketPrice'){
             let editField = dataCode === 'basePrice'?"base_price":"market_price";
             let newValue= scMathUtil.roundForObj(ci.value,decimal);
@@ -532,8 +584,8 @@ ProjectGLJ.prototype.changeIsEvaluate=function (id){
     let datas = projectGLJ.datas;
     let gljList = datas.gljList;
     let glj = _.find(gljList, {'id': id});
-    if(glj){
-        let con_key = gljOprObj.getIndex(glj,gljKeyArray);
+    if(glj){//与批量更新调用相同的方法
+     /*   let con_key = gljOprObj.getIndex(glj,gljKeyArray);
         let pratioM =datas.mixRatioConnectData[con_key];//找到父key
         let conditions = [];
         if(pratioM&&pratioM.length>0){
@@ -559,11 +611,55 @@ ProjectGLJ.prototype.changeIsEvaluate=function (id){
             rg.data.isEstimate =glj.is_evaluate?1:0;
             ration_nodes.push(rg);
         }
-        ration_nodes.length>0?projectObj.mainController.refreshTreeNode(ration_nodes):"";
+        ration_nodes.length>0?projectObj.mainController.refreshTreeNode(ration_nodes):"";*/
+        let [nodes,gljs] = projectGLJ.batchChangeIsEvaluate([glj]);
         projectObj.project.calcProgram.calcNodesAndSave(nodes);//触发计算程序
         return gljs;
     }
-}
+};
+
+/**
+ * 批量更新是否暂估
+ *传入项目工料机数组
+ */
+
+ProjectGLJ.prototype.batchChangeIsEvaluate=function (gljs){
+    let impactGLJs = [], changeArray =_.map(gljs,'id'),changeMap = _.indexBy(gljs,'id');;
+    for(let glj of gljs){
+        let con_key = gljOprObj.getIndex(glj,gljKeyArray);
+        let pratioM =this.datas.mixRatioConnectData[con_key];//找到父key
+        let conditions = [];
+        if(pratioM&&pratioM.length>0){
+            for(let p_key of pratioM ){
+                conditions.push(gljOprObj.getConditionByKey(p_key));
+            }
+        }
+        let tem_gljs = this.getProjectGLJs(conditions,false);
+        if(tem_gljs.length > 0) impactGLJs = impactGLJs.concat(tem_gljs);
+    }
+    impactGLJs = impactGLJs.concat(gljs);
+    impactGLJs =  _.uniq(impactGLJs,'id');//去重复
+
+    let impactRationNodes = this.getImpactRationNodes(impactGLJs);
+    let neeRefreshNode = [];
+    //更新对应的工料机类型的定额
+    for(let item of projectObj.project.Ration.datas){
+        if(item.type == rationType.gljRation && changeArray.indexOf(item.projectGLJID) != -1){
+            let tem_g = changeMap[item.projectGLJID];
+            item.isEstimate =tem_g.is_evaluate?1:0;
+            let ration_node = projectObj.project.mainTree.getNodeByID(item.ID);
+            neeRefreshNode?neeRefreshNode.push(ration_node):'';
+        }
+    }
+    let ration_glj_nodes = this.getMainAndEquGLJNodeByID(changeArray);//取显示在造价书界面上的主材和设备节点
+    for(let rg of ration_glj_nodes){
+        let tem_g = changeMap[rg.data.projectGLJID];
+        rg.data.isEstimate =tem_g.is_evaluate?1:0;
+        neeRefreshNode.push(rg);
+    }
+    neeRefreshNode.length>0?projectObj.mainController.refreshTreeNode(neeRefreshNode):"";
+    return [impactRationNodes,impactGLJs];
+};
 
 ProjectGLJ.prototype.getByID = function (ID) {
     return _.find(this.datas.gljList,{'id':ID});
@@ -591,9 +687,15 @@ ProjectGLJ.prototype.refreshTreeNodePriceIfNeed = function (data) {
 
 ProjectGLJ.prototype.getMainAndEquGLJNodeByID = function (id) {//通过ID取显示到主树上的主材和设备节点
     let nodes = [];
+    let ids = [];
+    if(Array.isArray(id)){
+        ids = id;
+    }else {
+        ids = [id];
+    }
     if(projectInfoObj.projectInfo.property.displaySetting.disPlayMainMaterial == true){
          nodes = _.filter(projectObj.project.mainTree.items, function (tem) {
-            return tem.sourceType == ModuleNames.ration_glj && tem.data.projectGLJID == id
+            return tem.sourceType == ModuleNames.ration_glj && ids.indexOf(tem.data.projectGLJID)  !== -1
         })
     }
     return nodes;

+ 1 - 2
web/building_saas/main/js/models/quantity_detail.js

@@ -677,6 +677,7 @@ var quantity_detail = {
                     project.projectGLJ.loadData();
                 });*/
                 project.calcProgram.calcNodesAndSave(needUpdateChildren, function () {
+                    project.projectGLJ.calcQuantity();
                     if(project.Bills.isFBFX(node)) { //判断是否属于分部分项工程 ,是的话才需要做计取安装费计算
                         project.installation_fee.calcInstallationFee(function (isChange,rations) {
                             if(isChange){
@@ -685,8 +686,6 @@ var quantity_detail = {
                                 });
                             }
                         });
-                    }else {
-                        project.projectGLJ.calcQuantity();
                     }
                 });
 

+ 4 - 0
web/building_saas/main/js/views/calc_base_view.js

@@ -315,6 +315,9 @@ let calcBaseView = {
                                 $.bootstrapLoading.end();
                             }
                         });
+                    }
+                    else{
+                        $('#errorInfo').html(analyzer.error);
                     };
                 }
                 else
@@ -409,6 +412,7 @@ $(document).ready(function () {
     });
 
     $('#qd-jsjs').on('hidden.bs.modal', function () {
+        $('#errorInfo').text('');
         //清空输入框
         calcBaseView.inputExpr.val('');
         calcBaseView.workBook.destroy();

+ 54 - 29
web/building_saas/main/js/views/calc_program_manage.js

@@ -60,6 +60,7 @@ let calcProgramManage = {
         me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.ValueChanged, me.onDetailValueChanged);
         me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.RangeChanged, me.onRangeChanged);
         me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.EnterCell, me.onDetailEnterCell);
+        me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.ClipboardPasting, me.onClipboardPasting);
 
         let mSheet = me.mainSpread.getSheet(0);
         sheetCommonObj.showData(mSheet, me.mainSetting, me.datas);
@@ -135,18 +136,35 @@ let calcProgramManage = {
         };
 
         curCalcItem[dataCode] = args.newValue;
-        let data = {
-            'projectID': projectObj.project.ID(),
-            'templatesID': template.ID,
-            'calcItem': curCalcItem
-        };
-        me.saveCalcItem(data, function (rst) {
-            if (rst){
-                let relationNodes = calcTools.getNodesByProgramID(template.ID);
-                projectObj.project.calcProgram.calcNodesAndSave(relationNodes);
-            }
-        });
-        $.bootstrapLoading.end();
+
+        if (dataCode == 'name'){
+            analyzer.refreshUsedCalcItemsStatement(template, curCalcItem);
+            let data = {
+                'projectID': projectObj.project.ID(),
+                'ID': template.ID,
+                'calcItems': template.calcItems
+            };
+            calcProgramManage.updateTemplate(data, function (rst) {
+                if (rst){
+                    calcProgramManage.refreshDetailSheet();
+                    $.bootstrapLoading.end();
+                }
+            });
+        }
+        else{
+            let data = {
+                'projectID': projectObj.project.ID(),
+                'templatesID': template.ID,
+                'calcItem': curCalcItem
+            };
+            me.saveCalcItem(data, function (rst) {
+                if (rst){
+                    let relationNodes = calcTools.getNodesByProgramID(template.ID);
+                    projectObj.project.calcProgram.calcNodesAndSave(relationNodes);
+                    $.bootstrapLoading.end();
+                }
+            });
+        }
     },
     onDetailEnterCell: function (sender, args) {
         // for test.
@@ -159,6 +177,9 @@ let calcProgramManage = {
         // let e = `ID:${c.ID} ${c.expression} ${c.dispExpr} ${c.dispExprUser} ${c.compiledExpr} ${c.custom}`;
         // projectObj.testDisplay('', e);
     },
+    onClipboardPasting: function (sender, args) {
+         args.cancel = true;
+    },
     loadMainContextMenu: function () {
         $.contextMenu({
             selector: '#mainSpread',
@@ -216,7 +237,7 @@ let calcProgramManage = {
                         let idx = calcProgramManage.mainSpread.getActiveSheet().getActiveRowIndex();
 
                         let newName = '';
-                        hintBox.valueBox('请输入新的模板名称:', template.name, function () {
+                        hintBox.valueBox('重命名', template.name, function () {
                             newName = hintBox.value;
 
                             if (!newName){
@@ -243,6 +264,7 @@ let calcProgramManage = {
                             calcProgramManage.updateTemplate(data, function (rst) {
                                 if (rst){
                                     projectObj.project.calcProgram.compileTemplateMaps();
+                                    projectObj.mainController.refreshTreeNode(calcTools.getNodesByProgramID(template.ID));
                                     sheetCommonObj.showData(calcProgramManage.mainSpread.getSheet(0), calcProgramManage.mainSetting, calcProgramManage.datas);
                                     $.bootstrapLoading.end();
                                 }
@@ -260,28 +282,29 @@ let calcProgramManage = {
                         return !canDelete;
                     },
                     callback: function () {
-                        $.bootstrapLoading.start();
                         let template = calcProgramManage.getSelectionInfo().template;
                         if (analyzer.templateIsUsed(template.ID)) {
                             $.bootstrapLoading.end();
                             hintBox.infoBox('系统提示', `计算模板“${template.name}”已被使用,不允许删除!`, 1);
                             return;
-                        }
-                        let data = {
-                            'projectID': projectObj.project.ID(),
-                            'ID': template.ID
                         };
-                        calcProgramManage.deleteTemplate(data, function (rst) {
-                            if (rst){
-                                let idx = calcProgramManage.mainSpread.getActiveSheet().getActiveRowIndex();
-                                projectObj.project.calcProgram.templates.splice(idx, 1);
-                                projectObj.project.calcProgram.compileTemplateMaps();
-                                calcProgramManage.buildSheet();
-                                calcProgramManage.mainSpread.getActiveSheet().setSelection(idx - 1, 0, 1, 1);
-                                calcProgramManage.refreshDetailSheet();
-                            }
-                        });
-                        $.bootstrapLoading.end();
+                        hintBox.infoBox('系统提示', `确定要删除计算模板“${template.name}”吗?`, 2, cbYes);
+                        function cbYes() {
+                            let data = {
+                                'projectID': projectObj.project.ID(),
+                                'ID': template.ID
+                            };
+                            calcProgramManage.deleteTemplate(data, function (rst) {
+                                if (rst){
+                                    let idx = calcProgramManage.mainSpread.getActiveSheet().getActiveRowIndex();
+                                    projectObj.project.calcProgram.templates.splice(idx, 1);
+                                    projectObj.project.calcProgram.compileTemplateMaps();
+                                    calcProgramManage.buildSheet();
+                                    calcProgramManage.mainSpread.getActiveSheet().setSelection(idx - 1, 0, 1, 1);
+                                    calcProgramManage.refreshDetailSheet();
+                                }
+                            });
+                        };
                     }
                 }
             }
@@ -399,11 +422,13 @@ let calcProgramManage = {
         );
     },
     deleteTemplate: function (data, callback) {
+        $.bootstrapLoading.start();
         CommonAjax.post('/calcProgram/deleteTemplate', data,
             function (result) {
                 if(callback){
                     callback(result);
                 }
+                $.bootstrapLoading.end();
             }
         );
     },

+ 85 - 9
web/building_saas/main/js/views/project_glj_view.js

@@ -250,6 +250,10 @@ projectGljObject={
         }else if(sheet.name() ==  'materialTreeSheet'){
             data = me.materialTree.selected.data;
             setting = me.materialSetting;
+            let notEditId= ['GC','GJ','MC','SN','SZ'];
+            if(notEditId.indexOf(data.id)!= -1){
+                return false;
+            }
         }
         let dataCode = setting.header[col].dataCode;
         let lockColumns = setting.view.lockColumns;
@@ -342,7 +346,7 @@ projectGljObject={
         if(canChange == false){//恢复原来的值
             info.sheetName =="materialTreeSheet"?me.showMaterialTreeData():me.showProjectGljData();
         }else if(info.sheetName =="projectGljSheet"){
-            me.batchUpdateProjectGLJ(changeInfo);
+            me.batchUpdateProjectGLJ(changeInfo,info.sheetName);
         }
     },
     onMixRatioRangeChange:function (sender,info){
@@ -376,18 +380,90 @@ projectGljObject={
 
 
     },
-    batchUpdateProjectGLJ:function(changeInfo){
+    batchUpdateProjectGLJ:function(changeInfo,sheetName){
         let projectGLJ = projectObj.project.projectGLJ;
         let me = projectGljObject;
-        me.batchUpdateGLJProperty(changeInfo);
-        projectGLJ.batchUpdatePrice(changeInfo,function (impactList) {
-            let selected = me.projectGljSheet.getSelections()[0];
-            me.showProjectGljData();
-            me.projectGljSheet.setSelection(selected.row,selected.col,selected.rowCount,selected.colCount);
+        let propertyCells=[],priceCells=[];
+        let setting = sheetName =="materialTreeSheet"?me.materialSetting:me.projectGljSetting;
+        for(let c of changeInfo){
+            c.dataCode = setting.header[c.col].dataCode;
+            if(c.dataCode == 'basePrice'||c.dataCode=='marketPrice'){
+                priceCells.push(c);
+            }else {
+                propertyCells.push(c);
+            }
+        }
+        me.batchUpdateGLJProperty(propertyCells,sheetName,function () {
+            //价格属于单价文件表,如果与项目工料机的其它属性一起的话计算起来会比较复杂,同时出现价格与其它属性一起更新的情况也会比较少;
+            projectGLJ.batchUpdatePrice(priceCells,sheetName,function (impactList) {
+                me.refreshBySheetName(sheetName);
+                gljOprObj.refreshView();
+            });
         });
     },
-    batchUpdateGLJProperty:function (changeInfo) {
-        console.log(changeInfo)
+    refreshBySheetName:function (sheetName) {
+        let me = projectGljObject;
+        if(sheetName =="projectGljSheet"){
+            me.showProjectGljData();
+        }else if(sheetName =="materialTreeSheet"){
+            me.showMaterialTreeData();
+        }
+    },
+
+    batchUpdateGLJProperty:function (changeInfo,sheetName,callback) {
+        let me = projectGljObject,updateMap = {};
+        let projectGLJ = projectObj.project.projectGLJ;
+        for(let c of changeInfo){
+            let recode = sheetName =="materialTreeSheet"?me.materialTree.items[c.row].data:me.projectGljSheetData[c.row];
+            if(recode[c.dataCode] == c.value){
+                continue;
+            }
+            me.getUpdateData(recode.id,c.value,c.dataCode,c.quantity,updateMap);
+        }
+        if(_.isEmpty(updateMap)){
+            callback?callback():'';
+            return;
+        }
+        projectGLJ.batchUpdateGLJProperty(updateMap,callback);
+    },
+    getUpdateData :function (id,value,dataCode,quantity,updateMap) {
+        let me = projectGljObject;
+        let supplyMap = {"自行采购":0,"部分甲供":1,"完全甲供":2,"甲定乙供":3};
+        let materialMap = {"钢材":1,"钢筋":2,"木材":3,"水泥":4,"标准砖":5};
+        let data = updateMap[id]?updateMap[id]:{};
+        //供货方式 和三材类型 粘贴和填充过来的数据,要做对应转换,因为这里value只是中文文本,并不是实际的值
+        // 如果是供货方式则需要处理数据
+        if (dataCode === 'supply') {
+            if(supplyMap[value]!==undefined||supplyMap[value]!==null){
+                value = supplyMap[value];
+            }
+            data.supply_quantity = me.getSupplyQuantity(value,quantity);
+        }
+        if(dataCode === 'supply_quantity'){//修改数量需做4舍5入
+            value =  scMathUtil.roundForObj(value,getDecimal('glj.quantity'));
+        }
+        if(dataCode === 'is_evaluate'||dataCode === 'is_adjust_price'||dataCode === 'is_main_material'){
+            if(value){
+                value = 1;
+            }else {
+                value = 0;
+            }
+        }
+        if(dataCode === 'materialType'){//三材类型要做对应转换,因为这里value只是中文文本,并不是实际的值
+            if(materialMap[value]!==undefined||materialMap[value]!==null){
+                value =  materialMap[value];
+            }
+            if(value == null || value==""){//删除三材类别时,清空三材系数
+                value = null;
+                data.materialCoe = null;
+            }
+        }
+        if(dataCode == 'materialCoe'){
+            value = scMathUtil.roundForObj(value,getDecimal("material"));
+        }
+
+        data[dataCode] = value ;
+        updateMap[id] = data;
     },
     batchUpdateConsumption:function(changeInfo){
         let projectGLJ = projectObj.project.projectGLJ;

+ 13 - 5
web/building_saas/main/js/views/project_view.js

@@ -7,7 +7,7 @@ var projectObj = {
     mainSpread: null,
     mainController: null,
     gljSpreed:null,
-    beforeMainTreeSelectedChange: function (pre,) {
+    beforeMainTreeSelectedChange: function (pre) {
         /*if (node) {
             subViewObj.saveComments(node);
         }*/
@@ -960,8 +960,10 @@ var projectObj = {
                          return project.Bills.isEngineerEst(project.mainTree.selected);//当焦点行是“专业工程暂估价”时,右键可见并有效。
                     },
                     callback: function () {
-                        projectObj.editContent(project.mainTree.selected,'engineeringContent');
-                        //BlockController.pasteBlock(project.mainTree.selected);
+                        let node = project.Bills.getNodeByFlag(project.mainTree.selected,fixedFlag.ENGINEERING_ESITIMATE);
+                        if(node){
+                            projectObj.editContent(node,'engineeringContent');
+                        }
                     }
                 },
                 "editService": {
@@ -971,7 +973,10 @@ var projectObj = {
                         return project.Bills.isTotalService(project.mainTree.selected);//当焦点行是“总承包服务费”时,右键可见并有效。
                     },
                     callback: function () {
-                        projectObj.editContent(project.mainTree.selected,'serviceContent');
+                        let node = project.Bills.getNodeByFlag(project.mainTree.selected,fixedFlag.TURN_KEY_CONTRACT);
+                        if(node){
+                            projectObj.editContent(node,'serviceContent');
+                        }
                     }
                 },
                 "editAccording": {
@@ -981,7 +986,10 @@ var projectObj = {
                         return project.Bills.isClaimVisa(project.mainTree.selected);//当焦点行是“签证及索赔计价”时,右键可见并有效。
                     },
                     callback: function () {
-                        projectObj.editContent(project.mainTree.selected,'claimVisa');
+                        let node = project.Bills.getNodeByFlag(project.mainTree.selected,fixedFlag.CLAIM_VISA);
+                        if(node){
+                            projectObj.editContent(node,'claimVisa');
+                        }
                     }
                 }
             }