瀏覽代碼

paste block

zhangweicheng 7 年之前
父節點
當前提交
98fd9c44e8

+ 1 - 0
config/gulpConfig.js

@@ -109,6 +109,7 @@ module.exports = {
         'web/building_saas/main/js/main_ajax.js',
         'web/building_saas/main/js/main.js',
         'web/building_saas/main/js/controllers/project_controller.js',
+        'web/building_saas/main/js/controllers/block_controller.js',
         'web/building_saas/main/js/views/side_tools.js',
         'web/building_saas/main/js/views/std_bills_lib.js',
         'web/building_saas/main/js/views/std_ration_lib.js',

+ 21 - 3
modules/main/controllers/bills_controller.js

@@ -7,7 +7,7 @@ let ration_model = require('../models/ration');
 let ProjectsData = require('../../pm/models/project_model').project;
 let logger = require("../../../logs/log_helper").logger;
 let quantity_detail = require("../facade/quantity_detail_facade");
-let bill_detail = require("../facade/bill_facade");
+let bill_facade = require("../facade/bill_facade");
 let ration_glj = mongoose.model('ration_glj');
 let ration_coe = mongoose.model('ration_coe');
 let rationInstallationModel = mongoose.model('ration_installation');
@@ -140,7 +140,7 @@ module.exports = {
         try {
             let data = req.body.data;
             data = JSON.parse(data);
-            let sectionInfo= await bill_detail.getSectionInfo(data);
+            let sectionInfo= await bill_facade.getSectionInfo(data);
             result.data=sectionInfo;
         }catch (err){
             logger.err(err);
@@ -156,7 +156,7 @@ module.exports = {
         try {
             let data = req.body.data;
             data = JSON.parse(data);
-            let reorganizeResult= await bill_detail.reorganizeFBFX(data);
+            let reorganizeResult= await bill_facade.reorganizeFBFX(data);
             result.data=reorganizeResult;
         }catch (err){
             logger.err(err);
@@ -165,6 +165,24 @@ module.exports = {
         }
         res.json(result);
     },
+    pasteBlock:async function(req,res){
+        let result={
+            error:0
+        }
+        try {
+            let data = req.body.data;
+            data = JSON.parse(data);
+            let pasteResult = await bill_facade.pasteBlock(data);
+            result.data = pasteResult;
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        res.json(result);
+    },
+
+
     upload: async function(req, res){
         let responseData = {
             err: 0,

+ 10 - 2
modules/main/facade/bill_facade.js

@@ -7,7 +7,7 @@ let Bills_Lib = mongoose.model('std_bills_lib_bills');
 let bill_Model = require('../models/bills').model;
 let _ = require("lodash");
 module.exports={
-   getSectionInfo : async function (data) {
+    getSectionInfo : async function (data) {
         let conditions=[];
         let fxList=[];
         let sectionInfo ={};
@@ -54,8 +54,16 @@ module.exports={
             result =await bill_Model.bulkWrite(tasks);
         }
         return result;
+    },
+    pasteBlock : async function(data){
+
+
+
+
+
+        console.log(data);
     }
-}
+};
 
 function generateBillTasks(data) {
     let tasks=[];

+ 1 - 0
modules/main/models/project_consts.js

@@ -45,4 +45,5 @@ let commonConst = {
     UT_DELETE: 'ut_delete'
 };
 
+
 module.exports = {projectConst: projectConst, commonConst: commonConst, projectConstList: projectConstList};

+ 1 - 0
modules/main/routes/bills_route.js

@@ -17,6 +17,7 @@ module.exports = function (app) {
     billsRouter.post('/multiDelete',billsController.multiDelete);
     billsRouter.post('/getSectionInfo', billsController.getSectionInfo);
     billsRouter.post('/reorganizeFBFX', billsController.reorganizeFBFX);
+    billsRouter.post('/pasteBlock', billsController.pasteBlock);
     billsRouter.post('/upload', billsController.upload);
     app.use('/bills', billsRouter);
 };

+ 136 - 20
web/building_saas/main/js/controllers/block_controller.js

@@ -88,7 +88,7 @@ let BlockController = {
             if(node.data.type == rationType.install){ //如果是生成的安装增加费,则跳过
                 return null;
             }
-            let gljList = ration_glj_Map[data.ID];//gljOprObj.filterGljByRation(node.data, datas);
+            let gljList = ration_glj_Map[data.ID]?ration_glj_Map[data.ID]:[];//gljOprObj.filterGljByRation(node.data, datas);
             gljList = gljOprObj.combineWithProjectGlj(gljList,false);
             data.ration_gljs = gljList;
             data.ration_coes = projectObj.project.ration_coe.getCoeByRationID(data.ID);
@@ -120,7 +120,7 @@ let BlockController = {
             if(selected.sourceType == ModuleNames.ration && selected.data.type != rationType.install ){//焦点行是定额/量价/工料机,则粘贴为后项
                 return "next";
             }
-            if(isFX(selected)||(selected.sourceType === Bills.getSourceType()&& selected.source.children.length == 0)){//焦点行是分项/叶子清单,且无基数计算,则粘贴到分项/叶子清单下
+            if(isFXorBX(selected)||(selected.sourceType === Bills.getSourceType()&& selected.source.children.length == 0)){//焦点行是分项/叶子清单,且无基数计算,则粘贴到分项/叶子清单下
                 if(selected.data.calcBase ==null||selected.data.calcBase ==undefined|| selected.data.calcBase == ""){//无基数计算
                     return "sub";
                 }
@@ -136,14 +136,14 @@ let BlockController = {
                 //默认为当前行的后项,可选前项、子项。
                 setRadioProp('sub_node',{checked:false,disabled:false});
             }
-            //复制块的第一层、焦点行的类型都是“分项”
-            if(blockData.firstNodeType == blockType.FX && isFX(selected)){
+            //复制块的第一层、焦点行的类型都是“分项”或补项
+            if(blockIsFXorBX(blockData.firstNodeType) && isFXorBX(selected)){
                 //默认为当前行的后项,可选前项,子项灰显不可选。
                 setRadioProp('sub_node',{checked:false,disabled:true});
             }
             //复制块的第一层是分项,焦点行是分部,且分部下无子项或者子项是分项
-            if(blockData.firstNodeType == blockType.FX && isFB(selected)){
-                if(selected.children.length == 0 || isFX(selected.children[0])){
+            if(blockIsFXorBX(blockData.firstNodeType)&& isFB(selected)){
+                if(selected.children.length == 0 || isFXorBX(selected.children[0])){
                     return 'sub';//不弹出选择窗口,直接粘贴为子项。
                 }
             }
@@ -172,9 +172,16 @@ let BlockController = {
            return selected.sourceType == Bills.getSourceType() && selected.data.type == billType.FB;
        }
 
-       function isFX(selected) {
-           return selected.sourceType == Bills.getSourceType() && selected.data.type == billType.FX;
+       function isFXorBX(selected) {//是分项或者补项
+            if(selected.sourceType == Bills.getSourceType()){
+                return   selected.data.type == billType.FX || selected.data.type == billType.BX;
+            }
+            return false;
+       }
+       function blockIsFXorBX(type) {
+           return type == blockType.FX||blockType.BX;
        }
+
     },
     /**
      * @param blockData
@@ -182,8 +189,12 @@ let BlockController = {
      * @param position next/pre/sub
      */
     confirmPaste:function (blockData,selected,position) {
+        let Bills = projectObj.project.Bills;
         let parent = null,next = null,pre = null;
-        if(blockDatacompilationID != projectInfoObj.projectInfo.compilation){//如果编办不一样,不能复制
+        let updateData = [],billUpdate = null;
+        let billsIDMap = {};//用来做新旧ID映射
+        if(blockData.compilationID != projectInfoObj.projectInfo.compilation){//如果编办不一样,不能复制
+            alert("编办不一致,不能粘贴!");
             return;
         }
         if(position == 'next'){ //插入为选中节点的后项,即选中节点为前项
@@ -198,30 +209,62 @@ let BlockController = {
         }
         if(position == 'sub'){//即选中节点为父项
             parent = selected;
-            next = selected.firstChild();
+            pre = selected.lastChild();
         }
-
+        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 = [];
+            }
+            //计算序列号
+            this.calcRationSerialNo(parentID,blockData,updateData,pre,next);
+        }else {
+            blockData.data.ParentID = parentID;
+            blockData.data.NextSiblingID=nextID;
+            if(pre){
+                billUpdate = {type:blockData.data.sourceType,query:{ID:pre.getID()},doc:{NextSiblingID:blockData.data.ID}};
+            }
+        }
+        let dataMap = this.preparePasteData(blockData.data,billsIDMap);
+        if(billUpdate){
+            billUpdate.doc.NextSiblingID = billsIDMap[billUpdate.doc.NextSiblingID];
+            updateData.push(billUpdate);
         }
+        dataMap.updateData = updateData;
+        console.log(dataMap);
+        $.bootstrapLoading.start();
+        CommonAjax.post('/bills/pasteBlock',dataMap,function (data) {
+             $.bootstrapLoading.end();
 
-        this.preparePasteData(blockData.data);
 
-        blockData.data = {};
-        console.log(blockData);
+        })
+
         //  delete fees / feesIndex /__v
     },
 
-    preparePasteData : function (data) {
+    preparePasteData : function (data,billsIDMap) {
         let me = this;
         me.datas = _.cloneDeep(projectObj.project.Bills.datas);
         let bills = [],rations=[],ration_gljs = [],ration_coes = [],quantity_details = [],ration_installations = [];
-        let billsIDMap = {};//用来做新旧ID映射
 
         eachData(data);
+        for(let b of bills){//更新ID
+            billsIDMap[b.ParentID]?b.ParentID = billsIDMap[b.ParentID]:'';
+            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) {
             if(data.sourceType == 'bills'){
                 let tem_b = createBillsData(data);
+                bills.push(tem_b);
                 for(let d of data.quantity_details){
                     quantity_details.push(createQuantityDetails(d,tem_b,'bills'));
                 }
@@ -230,15 +273,36 @@ let BlockController = {
                         eachData(c);
                     }
                 }
-                bills.push(tem_b);
             }
 
             if( data.sourceType == 'ration'){
                 let tem_r = createRationData(data);
                 rations.push(tem_r);
+                for(let d of data.quantity_details){
+                    quantity_details.push(createQuantityDetails(d,tem_r, 'ration'));
+                }
+                for(let g of data.ration_gljs){
+                    let tem_rg = createSubList(g,tem_r);
+                    tem_rg.billsItemID = tem_r.billsItemID;
+                    ration_gljs.push(tem_rg);
+                }
+                for(let o of data.ration_coes){
+                    ration_coes.push(createSubList(o,tem_r));
+                }
+                for(let ri of data.ration_installations){
+                    ration_installations.push(createSubList(ri,tem_r));
+                }
             }
 
+        }
 
+        function createSubList(subData,rationData) {
+            let tem_sub = _.cloneDeep(subData);
+            delete tem_sub._id;
+            tem_sub.ID = uuid.v1();
+            tem_sub.projectID = projectObj.project.ID();
+            tem_sub.rationID = rationData.ID;
+            return tem_sub;
         }
 
         function createQuantityDetails(detailData,pdata,type) {
@@ -263,12 +327,18 @@ let BlockController = {
             delete tem_ration.ration_coes;
             delete tem_ration.ration_installations;
             delete tem_ration.quantity_details;
+            delete tem_ration.__v;
+            delete tem_ration.sourceType;
 
             tem_ration.projectID = projectObj.project.ID();
             tem_ration.ID = uuid.v1();
             billsIDMap[tem_ration.billsItemID]?tem_ration.billsItemID = billsIDMap[tem_ration.billsItemID]:'';
 
-            //tem_ration.billsItemID
+            let firstLibID = rationLibObj.getFirstStdRationLibID();
+            if(firstLibID){
+                tem_ration.prefix = projectObj.project.Ration.getRationPrefix(firstLibID,tem_ration);
+            }
+            return tem_ration;
 
         }
 
@@ -279,12 +349,14 @@ let BlockController = {
             delete  temData.feesIndex;
             delete  temData.children;
             delete  temData.quantity_details;
+            delete  temData.__v;
+            delete  temData.sourceType;
 
             temData.projectID = projectObj.project.ID();
             let newID = uuid.v1(); //新的清单ID
             billsIDMap[temData.ID] = newID;
             temData.ID = newID; //新的清单ID
-            if(billsLibId&&billsLibId!=""&&temData.code.length == 12){//是从清单库来的
+            if(temData.billsLibId && temData.billsLibId!="" && temData.code.length == 12){//是从清单库来的
                 let value = temData.code.substr(0,9);
                 if (value&&value.length === 9 && /^[\d]+$/.test(value)) {
                     temData.code = projectObj.project.Bills.newFormatCode(value);
@@ -296,6 +368,50 @@ let BlockController = {
         }
     },
 
+    calcRationSerialNo:function (billsItemID,blockData,updateData,pre,next) {
+        let br = projectObj.project.Ration.getBillsSortRation(billsItemID);
+        if(next == null){ //没有下一树节点,即为最后节点
+            blockData.data.serialNo = 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;
+            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}});//更新兄弟节点序列号
+            }
+        }
+
+    },
+
+    calcRationQuantityAndContain : function (billsQuantity,ration) {//计算定额工程量和含量
+        let EXPString = ration.quantityEXP+"";
+        if(EXPString.indexOf("QDL") != -1){
+            if(EXPString=="QDL"){//定额的工程量是直接通过清单量填进来的;
+                let times = parseInt(ration.unit);
+                if(isNaN(times)){
+                    times = 1;
+                }
+                ration.quantity = scMathUtil.roundForObj(billsQuantity / times,getDecimal("ration.quantity"));
+                billsQuantity?ration.contain = scMathUtil.roundForObj(ration.quantity/billsQuantity,getDecimal("process")):ration.contain = 0;
+            } else {//如果定额的工程量是通过计算出来的,则应该重新计算。
+                let tem_contain = scMathUtil.roundForObj(ration.contain,getDecimal("process"));
+                let tem_quantity = scMathUtil.roundForObj(billsQuantity*tem_contain,getDecimal("ration.quantity")); //this.autoTransformQuantity(tem_quantity,rationNode);
+                ration.quantity = tem_quantity;
+            }
+        }else {//GCLMXHJ
+            let tem_contain=0;
+            if(billsQuantity&&billsQuantity!=0){
+                let children_quantity = scMathUtil.roundForObj(ration.quantity,getDecimal("ration.quantity"));
+                // children_quantity = scMathUtil.roundForObj(this.reverseQuantity(children_quantity,rationNode),getDecimal("quantity",rationNode));  原先是要反算的,现在改成不用反算了
+                tem_contain =scMathUtil.roundForObj(children_quantity/billsQuantity,getDecimal("process"));
+            }
+            ration.contain = tem_contain;
+        }
+    },
+
    newFormatCode : function (stdCode, filterCode) {
         let matchs = this.sameStdCode(stdCode, filterCode);
         let format = function (Number) {

+ 3 - 0
web/building_saas/main/js/models/cache_tree.js

@@ -143,6 +143,9 @@ var cacheTree = {
         Node.prototype.firstChild = function () {
             return this.children.length === 0 ? null : this.children[0];
         };
+        Node.prototype.lastChild = function () {
+            return this.children.length === 0 ? null : this.children[this.children.length - 1];
+        };
         Node.prototype.depth = function () {
             return this.parent ? this.parent.depth() + 1 : 0;
         };

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

@@ -452,6 +452,13 @@ var quantity_detail = {
             });
             return temp;
         };
+        quantity_detail.prototype.getDetailByRationID = function (rationID) {
+          return _.filter(this.datas,{'rationID':rationID});
+        };
+        quantity_detail.prototype.getDetailByBillID = function (billID) {
+            return _.filter(this.datas,{'billID':billID});
+        };
+
         quantity_detail.prototype.deleteByRation = function(ration){
             var detail_list = this.datas;
             _.remove(detail_list,{'rationID':ration.ID});
@@ -595,7 +602,7 @@ var quantity_detail = {
                     }else {
                         let tem_contain=0;
                         if(value&&value!=0){
-                           let children_quantity = scMathUtil.roundForObj(rationNode.data.quantity,getDecimal("quantity"),rationNode);
+                           let children_quantity = scMathUtil.roundForObj(rationNode.data.quantity,getDecimal("quantity",rationNode));
                             // children_quantity = scMathUtil.roundForObj(this.reverseQuantity(children_quantity,rationNode),getDecimal("quantity",rationNode));  原先是要反算的,现在改成不用反算了
                             tem_contain =scMathUtil.roundForObj(children_quantity/value,getDecimal("process"));
                         }

+ 4 - 0
web/building_saas/main/js/models/ration_coe.js

@@ -53,6 +53,10 @@ var ration_coe = {
                 }
             }
         };
+        ration_coe.prototype.getCoeByRationID = function (rationID) {
+           let coeList = _.filter(this.datas, {'rationID': rationID});
+           return coeList;
+        };
         ration_coe.prototype.refreshAfterUpdate=function(data){
             var coe_list = projectObj.project.ration_coe.datas;
             var coe_index= _.findIndex(coe_list,function(coe){

+ 4 - 0
web/building_saas/main/js/models/ration_installation.js

@@ -32,6 +32,10 @@ let ration_installation = {
                 }
             }
         };
+        ration_installation.prototype.getInstallationByRationID = function (rationID) {
+            let insList = _.filter(this.datas, {'rationID': rationID});
+            return insList;
+        };
         ration_installation.prototype.getBySectionID = function(sectionID){
             var ri_list = this.datas;
             return _.filter(ri_list,{'sectionId':sectionID});

+ 2 - 2
web/building_saas/main/js/views/glj_view.js

@@ -943,7 +943,7 @@ var gljOprObj = {
         }
         this.sheetData = newList;
     },
-    combineWithProjectGlj: function (ration_gljs) {
+    combineWithProjectGlj: function (ration_gljs,needRatio=true) {
         var projectGLJData = projectObj.project.projectGLJ.datas;
         var projectGljs = projectGLJData.gljList;
         var mixRatioMap = projectGLJData.mixRatioMap;
@@ -958,7 +958,7 @@ var gljOprObj = {
                     ration_gljs[i].isAdd = glj.unit_price.is_add;
                     ration_gljs[i]=this.setGLJPrice(ration_gljs[i],glj);//设置工料机价格
                     var connect_index = this.getIndex(glj, gljKeyArray);
-                    if (mixRatioMap.hasOwnProperty(connect_index)) {
+                    if (needRatio==true&&mixRatioMap.hasOwnProperty(connect_index)) {
                         var mixRatios = this.getMixRationShowDatas(mixRatioMap[connect_index], projectGljs);
                         ration_gljs[i].subList = mixRatios;
                     }

+ 53 - 11
web/building_saas/main/js/views/project_view.js

@@ -924,20 +924,13 @@ var projectObj = {
                     callback: function () {
                         project.calcProgram.calcAllNodesAndSave();
                     }
-                }/*,
+                },
                 "spr2":'--------',
                 "copyBlock": {
                     name: '复制整块',
                     icon: 'fa-copy',
                     disabled: function () {
-                        let selected = project.mainTree.selected;
-                        if(selected.sourceType == project.Bills.getSourceType() && selected.data.type == billType.DXFY){//焦点行是大项费用则无效;
-                            return true;
-                        }
-                        if(selected.sourceType == project.ration_glj.getSourceType()){// 焦点行是定额下的主材设备则无效;
-                            return true;
-                        }
-                        return false;
+                        return BlockController.copyBtnDisable(project.mainTree.selected);
                     },
                     callback: function () {
                         $.bootstrapLoading.start();
@@ -953,10 +946,13 @@ var projectObj = {
                 "pasteBlock": {
                     name: '粘贴整块',
                     icon: 'fa-paste',
+                    disabled: function (){
+                        return BlockController.pasteBtnDisable(project.mainTree.selected);
+                    },
                     callback: function () {
-
+                        BlockController.pasteBlock(project.mainTree.selected);
                     }
-                }*/
+                }
             }
         });
     },
@@ -1579,6 +1575,42 @@ $('#property_ok').click(function () {
     }
 });
 
+function testShow() {
+    var controller = projectObj.mainController, project = projectObj.project;
+    var selected = controller.tree.selected, parent = selected.parent;
+    var showinfo = "<label>确认要删除当前选中行吗?</label>";
+    var showN = false;
+    var cancelText = "否";
+    if(selected.sourceType == project.Bills.getSourceType()&&selected.data.type==billType.FB&&selected.children.length>0){//选中的是分部,并且有子项
+        if(isSingleSelect()||selectionChecking()){
+            showinfo = "<label>是否删除其下的子项?</label><br><label>【是】则删除分部行及其下的所有子项,</label><br><label>【否】则仅删除当前分部行,子项保留,</label><br><label>【取消】则取消删除</label>";
+            showN = true;
+            cancelText = "取消";
+        }
+    }
+    $('#delete_showinfo').html(showinfo);
+    showN==true? $('#deleteN').show():$('#deleteN').hide();
+    $('#deleteCancel').text(cancelText);
+
+    function selectionChecking() {
+        let selection = projectObj.mainSpread.getActiveSheet().getSelections()[0];
+        let mainTreeMap = {};
+        for(let i =0;i<selection.rowCount;i++){
+            let tem_node = controller.tree.items[selection.row+i];
+            if(i==0){//第一个直接添加;
+                mainTreeMap[tem_node.getID()] = tem_node;
+            }else {
+                project.Bills.setNodeToMap(tem_node,mainTreeMap);
+            }
+        }
+        let nodes = changeMapToArray(mainTreeMap);
+        if(nodes.length==1){
+            return true
+        }
+        return false;
+    }
+}
+
 $('#delete_row').on('shown.bs.modal', function (e) {
     var controller = projectObj.mainController, project = projectObj.project;
     var selected = controller.tree.selected, parent = selected.parent;
@@ -1858,6 +1890,16 @@ $(function () {
         spreadAutoFocus(subSpread,projectObj.mainSpread);
     });
 
+    $("#paste_confirm").click(function (){
+        let selected = projectObj.project.mainTree.selected;
+        let blockData = BlockController.getBlockData();
+        let position = $("input[name='pastePositionRadio']:checked").val();
+        BlockController.confirmPaste(blockData,selected,position);
+        $("#pastePosition").modal("hide");
+
+    });
+
+
     function spreadAutoFocus(spread,relateSpread) {
         if(relateSpread&&relateSpread.getActiveSheet().isEditing()){//关联的spread不在编辑状态的情况下,才自动获得焦点;
             return;