zhangweicheng 7 лет назад
Родитель
Сommit
6e11fbe842

+ 17 - 0
modules/fee_rates/controllers/fee_rates_controller.js

@@ -56,6 +56,7 @@ module.exports = {
     changeFeeRateFileFromOthers:changeFeeRateFileFromOthers,
     setFeeRateToBill:setFeeRateToBill,
     updateFeeRate:updateFeeRate,
+    updateFeeRates:updateFeeRates,
     updateRates:updateRates,
     feeRateFileSaveAs:feeRateFileSaveAs
 }
@@ -214,6 +215,22 @@ async function updateFeeRate(req,res) {
     res.json(result);
 }
 
+async function updateFeeRates(req,res) {
+    let result={
+        error:0
+    }
+    try {
+        let data = req.body.data;
+        let uresult= await feeRateFacde.updateFeeRates(data);
+        result.data=uresult;
+    }catch (err){
+        console.log(err);
+        result.error=1;
+        result.message = err.message;
+    }
+    res.json(result);
+}
+
 function updateRates(req,res){
     let result={
         error:0

+ 19 - 0
modules/fee_rates/facade/fee_rates_facade.js

@@ -30,6 +30,7 @@ module.exports={
     getGCFeeRateFiles: getGCFeeRateFiles ,
     setFeeRateToBill:setFeeRateToBill,
     updateFeeRate:updateFeeRate,
+    updateFeeRates:updateFeeRates,
     updateRates:update_rates,
     feeRateFileSaveAs:feeRateFileSaveAs,
     getFeeRateByID:getFeeRateByID
@@ -363,6 +364,24 @@ async function updateFeeRate(data) {
    return  await feeRateModel.findOneAndUpdate(data.query,data.doc);
 }
 
+async function updateFeeRates(datas){//批量更新费率
+    datas = JSON.parse(datas);
+    let tasks = [];
+    for(let d of datas){
+        let task = {
+                updateOne:{
+                    filter:d.query,
+                    update:d.doc
+                }
+        }
+        tasks.push(task);
+    }
+    tasks.length > 0 ?  await feeRateModel.bulkWrite(tasks) : '';
+    return 'OK';
+}
+
+
+
 async function changeFeeRateFileFromCurrent(jdata){
     let data = JSON.parse(jdata);
     let newFeeRateFile=data.newFeeRateFile;

+ 1 - 0
modules/fee_rates/routes/fee_rates_route.js

@@ -20,6 +20,7 @@ module.exports = function (app) {
     frRouter.post('/changeFeeRateFileFromOthers', frController.changeFeeRateFileFromOthers);
     frRouter.post('/setFeeRateToBill', frController.setFeeRateToBill);
     frRouter.post('/updateFeeRate', frController.updateFeeRate);
+    frRouter.post('/updateFeeRates', frController.updateFeeRates);
     frRouter.post('/updateRates', frController.updateRates);
     frRouter.post('/feeRateFileSaveAs', frController.feeRateFileSaveAs);
     app.use('/feeRates',frRouter);

+ 77 - 28
web/building_saas/main/js/controllers/block_controller.js

@@ -67,19 +67,32 @@ let BlockController = {
         return null;
     },
 
-    copyBlock:function (selected) {
+    copyBlock:function (selection) {
         let startTime = +new Date();
         let blockOjb = {
-            compilationID:projectInfoObj.projectInfo.compilation
+            compilationID:projectInfoObj.projectInfo.compilation,
+            datas:[]
         };
-        if(selected.sourceType == projectObj.project.Bills.getSourceType()){
-            blockOjb.firstNodeType = selected.data.type;
-        }else if(selected.sourceType == projectObj.project.Ration.getSourceType()){
+        let firstNode = projectObj.project.mainTree.items[selection.row];
+        let copyNodes = [firstNode];
+        if(selection.rowCount > 1){
+            for(let i = 1;i<selection.rowCount;i ++){
+                let temNode = projectObj.project.mainTree.items[selection.row + i];
+                if(this.copyBtnDisable(temNode) == false&&temNode.getParentID() != -1 && temNode.getParentID() == firstNode.getParentID() ){//多选时,与选中的第一个节点同一层次的才复制,即父节点一样的,其它的忽略,copyBtnDisable 判断要为false
+                    copyNodes.push(temNode);
+                }
+            }
+        }
+        if(firstNode.sourceType == projectObj.project.Bills.getSourceType()){
+            blockOjb.firstNodeType = firstNode.data.type;
+        }else if(firstNode.sourceType == projectObj.project.Ration.getSourceType()){
             blockOjb.firstNodeType = blockType.RATION;
         }
-        blockOjb.isFBFX = projectObj.project.Bills.isFBFX(selected);
+        blockOjb.isFBFX = projectObj.project.Bills.isFBFX(firstNode);
         let ration_glj_Map = _.groupBy(projectObj.project.ration_glj.datas, 'rationID');
-        blockOjb.data = this.getNodeDatas(selected,ration_glj_Map);
+        for(let cNode of copyNodes){
+            blockOjb.datas.push(this.getNodeDatas(cNode,ration_glj_Map));
+        }
         let getDataTime = +new Date();
         console.log(`复制所用时间——${getDataTime - startTime}`);
         blockOjb.copyTime = +new Date();//设置复制时间,可以用来做过期处理
@@ -142,8 +155,12 @@ let BlockController = {
         if(Bills.isFBFX(selected)){//  (2.1)、焦点行属于“分部分项工程”:
             //复制块的第一层、焦点行的类型都是“分部”
             if(blockData.firstNodeType == blockType.FB && isFB(selected)){
-                //默认为当前行的后项,可选前项、子项。
-                setRadioProp('sub_node',{checked:false,disabled:false});
+                if(selected.children.length > 0 && isFXorBX(selected.children[0])){//焦点行分部下有分项补项,弹出“粘贴位置选择”,默认为当前行的后项,可选前项,子项灰显。
+                    setRadioProp('sub_node',{checked:false,disabled:true});
+                }else {
+                    //默认为当前行的后项,可选前项、子项。
+                    setRadioProp('sub_node',{checked:false,disabled:false});
+                }
             }
             //复制块的第一层、焦点行的类型都是“分项”或补项
             if(blockIsFXorBX(blockData.firstNodeType) && isFXorBX(selected)){
@@ -202,6 +219,7 @@ let BlockController = {
         let project = projectObj.project;
         let Bills = project.Bills;
         let parent = null,next = null,pre = null;
+        let firstParentID = null, lastNextID = null;
         let updateData = [],billUpdate = null;
         let billsIDMap = {};//用来做新旧ID映射
         if(blockData.compilationID != projectInfoObj.projectInfo.compilation){//如果编办不一样,不能复制
@@ -225,23 +243,27 @@ let BlockController = {
         let parentID = parent?parent.getID():-1;
         let nextID = next?next.getID():-1;
         if(blockData.firstNodeType == blockType.RATION){ //复制的是定额,需根据新的父项信息和工程量明细计算工程量
-            blockData.data.billsItemID = parentID;
-            let billsQuantity = scMathUtil.roundForObj(parent.data.quantity,getDecimal("quantity",parent));
-            this.calcRationQuantityAndContain(billsQuantity,blockData.data);
-            //如果粘贴位置不属于分部分项工程,或者不是安装工程,则把安装增加费内容置空
-            if(!Bills.isFBFX(parent)|| projectInfoObj.projectInfo.property.engineering!=engineeringType.BUILD_IN){
-                blockData.data.ration_installations = [];
+            for(let d of blockData.datas){
+                d.billsItemID = parentID;
+                let billsQuantity = scMathUtil.roundForObj(parent.data.quantity,getDecimal("quantity",parent));
+                this.calcRationQuantityAndContain(billsQuantity,d);
+                //如果粘贴位置不属于分部分项工程,或者不是安装工程,则把安装增加费内容置空
+                if(!Bills.isFBFX(parent)|| projectInfoObj.projectInfo.property.engineering!=engineeringType.BUILD_IN){
+                    d.ration_installations = [];
+                }
             }
             //计算序列号
             this.calcRationSerialNo(parentID,blockData,updateData,pre,next);
         }else {
-            blockData.data.ParentID = parentID;
-            blockData.data.NextSiblingID=nextID;
+             firstParentID = parentID;
+             lastNextID = nextID;
+          /*  blockData.data.ParentID = parentID;
+            blockData.data.NextSiblingID = nextID;*/
             if(pre){
-                billUpdate = {type:blockData.data.sourceType,query:{ID:pre.getID()},doc:{NextSiblingID:blockData.data.ID}};
+                billUpdate = {type:blockData.datas[0].sourceType,query:{ID:pre.getID()},doc:{NextSiblingID:blockData.datas[0].ID}};
             }
         }
-        let dataMap = this.preparePasteData(blockData.data,billsIDMap);
+        let dataMap = this.preparePasteData(blockData.datas,billsIDMap,firstParentID,lastNextID);
         if(billUpdate){
             billUpdate.doc.NextSiblingID = billsIDMap[billUpdate.doc.NextSiblingID];
             updateData.push(billUpdate);
@@ -358,16 +380,39 @@ let BlockController = {
 
     },
 
-    preparePasteData : function (data,billsIDMap) {
+    preparePasteData : function (datas,billsIDMap,firstParentID,lastNextID) {
         let me = this;
         me.datas = _.cloneDeep(projectObj.project.Bills.datas);
         let bills = [],rations=[],ration_gljs = [],ration_coes = [],quantity_details = [],ration_installations = [];
+        let firstBillIDs = [],lastBillID = null;//记录第一层清单的ID,和第一层的最后一个清单ID
+        let firstIDMap = {};
+        for(let i = 0 ;i< datas.length ;i++){
+            if(datas[i].sourceType == 'bills'){
+                firstBillIDs.push(datas[i].ID);
+                if(i == datas.length -1){//最后一个清单节点
+                    lastBillID =  datas[i].ID
+                }
+            }
+            eachData(datas[i]);
+        }
+        for(let f of firstBillIDs){
+            firstIDMap[billsIDMap[f]]  = f //反向映射
+        }
 
-        eachData(data);
         for(let b of bills){//更新ID
-            billsIDMap[b.ParentID]?b.ParentID = billsIDMap[b.ParentID]:'';
-            billsIDMap[b.NextSiblingID]?b.NextSiblingID = billsIDMap[b.NextSiblingID]:'';
+            if(firstIDMap[b.ID]) {//如果是第一层清单节点对应的数据,更新父ID 为当前树中的父ID
+                b.ParentID = firstParentID;
+            }else {
+                billsIDMap[b.ParentID]?b.ParentID = billsIDMap[b.ParentID]:'';
+            }
+            if(b.ID == billsIDMap[lastBillID]){//如果是第一层清单最后节点对应的数据,更新下一节点ID为插入位置的下一个节点ID
+                b.NextSiblingID = lastNextID;
+            }else {
+                billsIDMap[b.NextSiblingID]?b.NextSiblingID = billsIDMap[b.NextSiblingID]:'';
+            }
         }
+
+
         return {bills:bills,rations:rations,ration_gljs:ration_gljs,ration_coes:ration_coes,quantity_details:quantity_details,ration_installations:ration_installations};
 
         function eachData(data) {
@@ -482,20 +527,24 @@ let BlockController = {
 
     calcRationSerialNo:function (billsItemID,blockData,updateData,pre,next) {
         let br = projectObj.project.Ration.getBillsSortRation(billsItemID);
+        let firstSerialNo = 0;
         if(next == null){ //没有下一树节点,即为最后节点
-            blockData.data.serialNo = br.length > 0 ? br[br.length - 1].serialNo + 1 : 1;
+            firstSerialNo = br.length > 0 ? br[br.length - 1].serialNo + 1 : 1;
         }else {//有下一节点
             let startIndex =0;
             if(pre){
                 startIndex = br.indexOf(pre.data)+1;
             }
-            blockData.data.serialNo = br[startIndex].serialNo;
+            firstSerialNo = br[startIndex].serialNo;
             for(let i = startIndex;i < br.length; i++){
-                let br_serialNo =  i < br.length - 1 ? br [i + 1].serialNo : br[i].serialNo + 1;
-                updateData.push({type:blockData.data.sourceType,query:{ID:br[i].ID},doc:{serialNo:br_serialNo}});//更新兄弟节点序列号
+                let br_serialNo =  br[i].serialNo + blockData.datas.length;    //i < br.length - 1 ? br [i + 1].serialNo : br[i].serialNo + 1;
+                 updateData.push({type:blockData.datas[0].sourceType,query:{ID:br[i].ID},doc:{serialNo:br_serialNo}});//更新兄弟节点序列号
             }
         }
-
+        for(let i = 0 ; i < blockData.datas;i++){
+            blockData.datas[i] = firstSerialNo;
+            firstSerialNo += 1;
+        }
     },
     calcRationQuantityAndContain : function (billsQuantity,ration) {//计算定额工程量和含量
         let EXPString = ration.quantityEXP+"";

+ 56 - 5
web/building_saas/main/js/models/fee_rate.js

@@ -184,9 +184,26 @@ var FeeRate = {
             }
         };
         FeeRate.prototype.onFeeRateChange=function (rateID,value) {
-            var node = project.mainTree.selected;
-            this.refreshCalProgramByRateID(rateID,value);
-            this.refreshBillsByRateID(rateID,value);
+           /* var node = project.mainTree.selected;
+             this.refreshCalProgramByRateID(rateID,value);
+             this.refreshBillsByRateID(rateID,value);
+             if(node){
+             if (node.sourceType==='ration' && calcProgramObj.sheet) {
+             calcProgramObj.showData(node);
+             }
+             }
+             project.calcProgram.calcAllNodesAndSave(calcAllType.catAll);
+             project.markUpdateProject({projectID:project.ID(),feeRateID:this.getActivateFeeRateFileID()},"feeRate");
+             socket.emit('feeRateChangeNotify', this.getActivateFeeRateFileID());*/
+           this.onFeeRatesChange([{rateID:rateID,value:value}]);
+        };
+
+        FeeRate.prototype.onFeeRatesChange = function (infos) {//{rateID:'AAAA',value:23}
+            let node = project.mainTree.selected;
+            for(let i of infos){
+                this.refreshCalProgramByRateID(i.rateID,i.value);
+                this.refreshBillsByRateID(i.rateID,i.value);
+            }
             if(node){
                 if (node.sourceType==='ration' && calcProgramObj.sheet) {
                     calcProgramObj.showData(node);
@@ -196,6 +213,8 @@ var FeeRate = {
             project.markUpdateProject({projectID:project.ID(),feeRateID:this.getActivateFeeRateFileID()},"feeRate");
             socket.emit('feeRateChangeNotify', this.getActivateFeeRateFileID());
         };
+
+
         FeeRate.prototype.onFeeRateFileChange=function () {//整个费率文件换了,原费率文件内容不变
             this.refreshCalProgramWhenFeeFileChange();
             this.refreshBillsWhenFeeFileChange();
@@ -415,7 +434,7 @@ var FeeRate = {
 
         FeeRate.prototype.updateFeeRateByID = function (rateID,doc,callback) {
           let me = this,preKey = 'rates.$.';
-          let data = {
+          /*let data = {
               query:{
                   'ID':me.getActivateFeeRateID(),
                   'rates.ID':rateID
@@ -434,9 +453,41 @@ var FeeRate = {
             if(callback){
                 callback();
             }
-          });
+          });*/
+          me.updateFeeRatesByIDs([{rateID:rateID,doc:doc}],callback);
+
         };
 
+        FeeRate.prototype.updateFeeRatesByIDs = function(datas,callback){
+            let me = this,preKey = 'rates.$.';
+            let updateDatas = [];
+            for(let d of datas){
+                let u = {
+                    query:{
+                        'ID':me.getActivateFeeRateID(),
+                        'rates.ID':d.rateID
+                    },
+                    doc:{}
+                }
+                for(let prop in d.doc){//做了个转换,加上前缀
+                    u.doc[preKey+prop] = d.doc[prop];
+                }
+                updateDatas.push(u);
+            }
+            CommonAjax.post('/feeRates/updateFeeRates', updateDatas, function (result) {
+                //更新缓存
+                for(let d of datas){
+                    let rate = me.getFeeRateByID(d.rateID);
+                    for(let dkey in d.doc){
+                        rate[dkey] = d.doc[dkey];
+                    }
+                }
+                if(callback){
+                    callback();
+                }
+            });
+
+        };
         FeeRate.prototype.getfbUpdateData=function (rate,bill,value,editText) {
             var data=null;
             if(bill.feeRateID&&editText!=null){

+ 75 - 6
web/building_saas/main/js/views/fee_rate_view.js

@@ -388,11 +388,10 @@ var feeRateObject={
         sheetCommonObj.lockCells(this.mainFeeRateSheet , this.mainFeeRateSetting);
         this.mainFeeRateSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onMainFeeRateSheetValueChange);
         this.mainFeeRateSheet.bind(GC.Spread.Sheets.Events.SelectionChanged, this.onMainFeeRateSelectChanged);
+        this.mainFeeRateSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onMainFeeRateRangeChanged);
         this.mainFeeRateSheet.bind(GC.Spread.Sheets.Events.EditStarting, function (e,args) {
-            let me =feeRateObject, row = args.row;
-            let recode = me.mainFeeRateData[row];
-            let dataCode = me.mainFeeRateSetting.header[args.col].dataCode;
-            if(dataCode=="rate"&&me.getChildrenCount(recode.ID,me.mainFeeRateData)>0){//有子节点时不能编辑费率列
+            let me =feeRateObject;
+            if(!me.mainFeeRateEditChecking(args.row,args.col)){
                 args.cancel = true;
             }
         });
@@ -416,8 +415,18 @@ var feeRateObject={
             subRateObject.initSubRateSpread(this.mainFeeRateData[0]);
         }
     },
+    mainFeeRateEditChecking:function (row,col) {//false 不能编辑,true 可以编辑
+        let me =feeRateObject;
+        let recode = me.mainFeeRateData[row];
+        let dataCode = me.mainFeeRateSetting.header[col].dataCode;
+        if(dataCode=="rate"&&me.getChildrenCount(recode.ID,me.mainFeeRateData)>0){//有子节点时不能编辑费率列
+            return false;
+        }
+        return true;
+    },
+
     onMainFeeRateSheetValueChange:function (e,info) {
-        let me = feeRateObject,updateData = {},feeRate = projectObj.project.FeeRate;
+  /*      let me = feeRateObject,updateData = {},feeRate = projectObj.project.FeeRate;
         let recode = me.mainFeeRateData[info.row];
         let fieldID = me.mainFeeRateSetting.header[info.col].dataCode;
         let value = info.newValue;
@@ -442,9 +451,69 @@ var feeRateObject={
                 feeRate.onFeeRateChange(recode.ID,value);
             }
             $.bootstrapLoading.end();
-        })
+        })*/
+        feeRateObject.updateFeerateWhenCellsChange([info]);
+    },
+    onMainFeeRateRangeChanged:function (e,info) {
+        let me = feeRateObject;
+        let changeCells = [];
+        for(let c of info.changedCells){
+            let tem = {
+                row:c.row,
+                col:c.col,
+                newValue:info.sheet.getCell(c.row,c.col).value()
+            };
+            changeCells.push(tem);
+        }
+        me.updateFeerateWhenCellsChange(changeCells);
     },
 
+    updateFeerateWhenCellsChange:function (cells) {// col,row,newValue
+        let me = feeRateObject,updateDatas = [],feeRate = projectObj.project.FeeRate;//[{rateID:rateID,doc:doc}]
+        let refreshA = [];//记录刷新条数的数组
+        for(let c of cells){
+            let temData = {};
+            let recode  = me.mainFeeRateData[c.row];
+            let fieldID = me.mainFeeRateSetting.header[c.col].dataCode;
+            let value = c.newValue;
+            let oldValue = recode[fieldID];
+            if(!me.mainFeeRateEditChecking(c.row, c.col)){
+                me.mainFeeRateSheet.setValue(c.row, c.col, oldValue);
+                continue;
+            }else if(fieldID == 'rate'&&value != null){
+                let checkResult = scMathUtil.isNumOrFormula(value);
+                if(checkResult!=null && !isNaN(checkResult)){
+                    value = scMathUtil.roundForObj(checkResult,getDecimal("feeRate"));
+                }else {
+                    setTimeout(function () {
+                        alert('当前输入的数据类型不正确,请重新输入。');
+                    },100);
+                    me.mainFeeRateSheet.setValue(c.row, c.col, oldValue);
+                    continue;
+                }
+            }
+            if(recode[fieldID] == value){//没有改变
+                continue;
+            }
+            temData[fieldID] = value ;
+            updateDatas.push({rateID:recode.ID,doc:temData});
+            refreshA.push({col:c.col,row:c.row,fieldID:fieldID,value:value,rateID:recode.ID});
+        }
+        if(updateDatas.length > 0){
+            $.bootstrapLoading.start();
+            feeRate.updateFeeRatesByIDs(updateDatas,function () {
+                let feerateInfo = [];
+                for(let r of refreshA){
+                    me.mainFeeRateSheet.setValue(r.row, r.col, r.value);
+                    if(r.fieldID == 'rate'){
+                        feerateInfo.push({rateID:r.rateID,value:r.value});
+                    }
+                }
+                feerateInfo.length > 0 ?feeRate.onFeeRatesChange(feerateInfo):'';
+                $.bootstrapLoading.end();
+            })
+        }
+    },
     onMainFeeRateSelectChanged:function (e, info) {
         let me = feeRateObject;
         let row = info.newSelections[0].row;

+ 6 - 3
web/building_saas/main/js/views/project_view.js

@@ -948,13 +948,16 @@ var projectObj = {
                     name: '复制整块',
                     icon: 'fa-copy',
                     disabled: function () {
-                        return BlockController.copyBtnDisable(project.mainTree.selected);
+                        let selection = projectObj.mainSpread.getActiveSheet().getSelections()[0];
+                        let firstNode = projectObj.project.mainTree.items[selection.row];//当多选的情况,用mainTree.selected判断不正确,要用第一个选中的节点
+                        return BlockController.copyBtnDisable(firstNode);
                     },
                     callback: function () {
                         $.bootstrapLoading.start();
-                        let selected = project.mainTree.selected;
+                        //let selected = project.mainTree.selected;
+                        let selections = projectObj.mainSpread.getActiveSheet().getSelections();
                         setTimeout(function () {
-                            BlockController.copyBlock(selected);
+                            BlockController.copyBlock(selections[0]);
                             $.bootstrapLoading.end();
                         },100)