/**
 * Created by zhang on 2018/5/10.
 */
let BlockController = {
    datas:[],
    disabelCopyRightClick:function(){
        if (projectReadOnly) {
            return true;
        }
        let selection = projectObj.mainSpread.getActiveSheet().getSelections()[0];
        let firstNode = projectObj.project.mainTree.items[selection.row];//当多选的情况，用mainTree.selected判断不正确,要用第一个选中的节点
        for(let i = 0;i< selection.rowCount;i++){ //多选的时候判断所有与第一个节点同级的节点
            let temNode = projectObj.project.mainTree.items[selection.row + i];
            if(firstNode.getParentID() == temNode.getParentID()){
                if(BlockController.copyBtnDisable(temNode) == true){
                    return true;
                }
            }
        }
        return false;
    },
    copyRightClickCallback:function(){
        $.bootstrapLoading.start();
        //let selected = project.mainTree.selected;
        let selections = projectObj.mainSpread.getActiveSheet().getSelections();
        setTimeout(function () {
            BlockController.copyBlock(selections[0]);
            $.bootstrapLoading.end();
        },100)
    },
    copyBtnDisable:function (selected) {
        if(this.isDXFYorMainEq(selected)){
            return true;
        }
        if(selected.sourceType == ModuleNames.ration && selected.data.type == rationType.install){
            return true;
        }
        if (OVER_HEIGHT.isOverHeight(selected)) {
            return true;
        }
        if(projectObj.project.Bills.hasFlags(selected)){//所有固定清单项不能复制
            return true;
        }
        //

        return false;
    },
    pasteBtnDisable:function (selected) {
        let blockData = this.getBlockData();
        let Bills = projectObj.project.Bills;
        if(this.isDXFYorMainEq(selected)){
            return true;
        }
        if(blockData == null){
            return true;
        }
        if(blockData.firstNodeType != blockType.RATION ){//复制的不是定额
          //&& blockData.isFBFX !=  Bills.isFBFX(selected)  
          if (this.blockIsFB(blockData.firstNodeType) && !Bills.isFBFX(selected)) return true; //第一层是分部，不允许复制到非分部分项
          //分项\补项不允许粘贴到“施工组织措施项目”下
          if (this.blockIsFXorBX(blockData.firstNodeType) && Bills.isOrgMeasure(selected)) return true;
          
          if (blockData.firstNodeType == blockType.BILL && Bills.isFBFX(selected) ) { //如果是清单 到分部分项          
            for (let d of blockData.datas) { 
               //如果清单有多层，不允许复制 
              if (!this.blockIsLeaveBills(d)) return true;
              ///如果有清单基数，不允许复制
              if (this.ifCalcBase(d.calcBase)) return true;
               //如果清单有费率引用，不允许复制
              if (gljUtil.isNotEmpty(d.feeRateID)) return true;
            }
          }
        }
        if(this.blockIsFXorBX(blockData.firstNodeType) && this.isFB(selected)){//复制块的第一层是分项或补项，焦点行是分部，且分部有子项并且子项不是分项或补项，则无效。
            if(selected.children.length && !this.isFXorBX(selected.children[0])){
                return true;
            }
        }

        if(this.isFXorBX(selected) && blockData.firstNodeType == blockType.FB){//焦点行是分项或补项，复制块的第一层是分部，则无效。
            return true;
        }
        if(blockData.firstNodeType == blockType.RATION && selected.sourceType == Bills.getSourceType()){ //复制的是定额/量价/工料机、焦点行是分部/清单父项则无效
            if( selected.data.type == billType.FB ){
                return true;
            }
            if(MainTreeCol.readOnly.billsParent(selected)){
                return true;
            }
            if(this.haveCalcBase(selected)){//有使用基数计算，disable
                return true;
            }
        }
        if(blockData.firstNodeType != blockType.RATION && selected.sourceType == ModuleNames.ration){
            return true;
        }
        return false;
    },
    // 恢复删除节点有效性
    recoverBlockDisabled: function () {
        if (projectReadOnly) {
            return true;
        }
        const recycle = getLocalCache('project_recycle');
        if (!recycle) {
            return true;
        }
        const recycleObj = JSON.parse(recycle);
        const firstData = recycleObj.datas.length ? recycleObj.datas[0] : null;
        if (!firstData || firstData.projectID !== projectObj.project.ID()) {
            return true;
        }
        const parentID = firstData.sourceType === projectObj.project.Bills.getSourceType() ? firstData.ParentID : firstData.billsItemID;
        const parent = projectObj.project.mainTree.findNode(parentID);
        // parentID为-1时，为大项费用
        if (parentID !== -1 && !parent) {
            return true;
        }
        return false;
    },
    haveCalcBase : function (node) {
      return this.ifCalcBase(node.data.calcBase);
    },
    ifCalcBase: function (calcBase) {
      if (calcBase == null || calcBase == undefined || calcBase == "") {
        return false;
      }
      return true;
    },
    isDXFYorMainEq:function (node) {//焦点行是大项费用或定额下的主材设备
        if(node.sourceType == ModuleNames.bills && node.data.type == billType.DXFY){//焦点行是大项费用则无效；
            return true;
        }
        if(node.sourceType == ModuleNames.ration_glj){// 焦点行是定额下的主材设备则无效；
            return true;
        }
        return false;
    },

    getBlockData:function () {
        let blockString =getLocalCache('project_block');
        if(blockString !=null){
            return JSON.parse(blockString);
        }
        return null;
    },
    extractBlockData: function (selection) {
        let startTime = +new Date();
        let blockObj = {
            compilationID:projectObj.project.projectInfo.compilation,
            datas:[]
        };
        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()){
            // 特殊处理大项费用，因为DXFY在billType中为1，与blockType中的RATION冲突了
            blockObj.firstNodeType = firstNode.data.type === billType.DXFY ? blockType.DXFY : firstNode.data.type;
        }else if(firstNode.sourceType == projectObj.project.Ration.getSourceType()){
            blockObj.firstNodeType = blockType.RATION;
        }
        blockObj.isFBFX = projectObj.project.Bills.isFBFX(firstNode);
        let ration_glj_Map = _.groupBy(projectObj.project.ration_glj.datas, 'rationID');
        for(let cNode of copyNodes){
            blockObj.datas.push(this.getNodeDatas(cNode,ration_glj_Map));
        }
        let getDataTime = +new Date();
        console.log(`复制所用时间——${getDataTime - startTime}`);
        blockObj.copyTime = +new Date();//设置复制时间，可以用来做过期处理
        setLocalCache('project_block',JSON.stringify(blockObj));
        let endTime = +new Date();
        console.log(`复制所用时间——${endTime - startTime}`);
        return blockObj;
    },
    copyBlock:function (selection) {
        const block = this.extractBlockData(selection);
        setLocalCache('project_block', JSON.stringify(block));
    },
    recycleBlock: function (selection) {
        const block = this.extractBlockData(selection);
        setLocalCache('project_recycle', JSON.stringify(block));
    },
    getNodeDatas : function (node,ration_glj_Map) {
        let data = node.data;
        data.sourceType =  node.sourceType;
        if(node.sourceType == projectObj.project.Bills.getSourceType()){
            data.quantity_details = projectObj.project.quantity_detail.getDetailByBillID(data.ID);
        }
        if(node.sourceType == projectObj.project.Ration.getSourceType()){
            if(node.data.type == rationType.install){ //如果是生成的安装增加费，则跳过
                return null;
            }
            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);
            data.ration_installations =  projectObj.project.ration_installation.getInstallationByRationID(data.ID);
            data.quantity_details = projectObj.project.quantity_detail.getDetailByRationID(data.ID);
            data.ration_template = projectObj.project.ration_template.getTemplateByRationID(data.ID);
        }else if(node.children.length>0){
            let children = [];
            for(let c of node.children){
                let tem_data = this.getNodeDatas(c,ration_glj_Map);
                tem_data?children.push(tem_data):'';
            }
            data.children = children;
        }
        return data;
    },
    pasteBlock:function (selected) {
        let blockData = this.getBlockData();
        let position = this.initOptionDiv(selected,blockData);
        if(position == null){
            return;
        }
        this.confirmPaste(blockData,selected,position);
        //do paste
    },
    // 恢复删除节点
    recoverBlock: function () {
        const recycle = JSON.parse(getLocalCache('project_recycle'));
        const firstData = recycle.datas[0];
        const parentID = firstData.sourceType === projectObj.project.Bills.getSourceType() ? firstData.ParentID : firstData.billsItemID;
        // 恢复到父节点最末子项
        if (parentID !== -1) {
            const parent = projectObj.project.mainTree.findNode(parentID);
            this.confirmPaste(recycle, parent, 'sub');
        } else {
            // 恢复到最末根节点后项
            const lastRoot = projectObj.project.mainTree.roots[projectObj.project.mainTree.roots.length - 1];
            this.confirmPaste(recycle, lastRoot, 'next');
        }
    },
    initOptionDiv:function (selected,blockData) {
        let Bills = projectObj.project.Bills;
        if( blockData.firstNodeType == blockType.RATION){//如果剪切板中是复制的定额块
            if(selected.sourceType == ModuleNames.ration && selected.data.type != rationType.install ){//焦点行是定额/量价/工料机，则粘贴为后项
                return "next";
            }
            if(this.isFXorBX(selected)||(selected.sourceType === Bills.getSourceType()&& selected.source.children.length == 0)){//焦点行是分项/叶子清单，且无基数计算，则粘贴到分项/叶子清单下
                if(!this.haveCalcBase(selected)){//无基数计算
                    return "sub";
                }
            }
        }

        //设置选项的初始值
        setRadioProp('next_node',{checked:true,disabled:false});
        setRadioProp('pre_node',{checked:false,disabled:false});
        if(Bills.isFBFX(selected)){//  (2.1)、焦点行属于“分部分项工程”：
            //复制块的第一层、焦点行的类型都是“分部”
            if(blockData.firstNodeType == blockType.FB && this.isFB(selected)){
                if(selected.children.length > 0 && this.isFXorBX(selected.children[0])){//焦点行分部下有分项补项，弹出“粘贴位置选择”，默认为当前行的后项，可选前项，子项灰显。
                    setRadioProp('sub_node',{checked:false,disabled:true});
                }else {
                    //默认为当前行的后项，可选前项、子项。
                    setRadioProp('sub_node',{checked:false,disabled:false});
                }
            }
            //复制块的第一层、焦点行的类型都是“分项”或补项
            if(this.blockIsFXorBX(blockData.firstNodeType) && this.isFXorBX(selected)){
                //默认为当前行的后项，可选前项，子项灰显不可选。
                setRadioProp('sub_node',{checked:false,disabled:true});
            }
            //复制块的第一层是分项，清单，焦点行是分部，且分部下无子项或者子项是分项
            if((blockData.firstNodeType ==blockType.BILL||  this.blockIsFXorBX(blockData.firstNodeType))&& this.isFB(selected)){
                if(selected.children.length == 0 || this.isFXorBX(selected.children[0])){
                    return 'sub';//不弹出选择窗口,直接粘贴为子项。
                }
            }
        }else {//焦点行不属于“分部分项工程”
            if(blockData.firstNodeType == blockType.BILL &&selected.sourceType == Bills.getSourceType()){//如果剪切板中是从“分部分项工程”以外复制的清单块
                if(selected.children.length==0 || selected.children[0].sourceType == Bills.getSourceType()){//焦点行没有子项，或者子项是清单，判断是否有基数计算
                    if(this.haveCalcBase(selected)){//如果焦点行有基数计算，则子项灰显不可选。
                        setRadioProp('sub_node',{checked:false,disabled:true});
                    }else{//如果焦点行没有基数计算，则子项可选。
                        setRadioProp('sub_node',{checked:false,disabled:false});
                    }
                }else {
                    setRadioProp('sub_node',{checked:false,disabled:true});
                }
            }
        }
        $("#pastePosition").modal({show:true});
        return null;

       function setRadioProp(id,options) {
           $("#"+id).prop("checked",options.checked);
           $("#"+id).prop("disabled",options.disabled);
       }
    },
    /**
     * @param blockData
     * @param selected
     * @param position next/pre/sub
     */
    confirmPaste:function (blockData,selected,position,callback) {
        let me = this;
        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 != projectObj.project.projectInfo.compilation){//如果编办不一样，不能复制
            alert("编办不一致，不能粘贴！");
            return;
        }
        if(position == 'next'){ //插入为选中节点的后项,即选中节点为前项
            parent = selected.parent;
            next = selected.nextSibling;
            pre = selected;
        }
        if(position == 'pre'){//插入为选中节点的前项,即选中节点为后项
            parent = selected.parent;
            next = selected;
            pre = selected.preSibling;
        }
        if(position == 'sub'){//即选中节点为父项
            parent = selected;
            pre = selected.lastChild();
        }
        let parentID = parent?parent.getID():-1;
        let nextID = next?next.getID():-1;
        if(blockData.firstNodeType == blockType.RATION){ //复制的是定额，需根据新的父项信息和工程量明细计算工程量
            for(let d of blockData.datas){
                d.billsItemID = parentID;
                if (blockData.zeroQuantity){   // 来自克隆块
                    d.quantity = 0;
                    d.quantityEXP = '';
                    d.contain = '';
                }else{
                    let billsQuantity = scMathUtil.roundForObj(parent.data.quantity,getDecimal("quantity",parent));
                    this.calcRationQuantityAndContain(billsQuantity,d,parent.data.unit);
                }

                //如果粘贴位置不属于分部分项工程，或者不是安装工程，则把安装增加费内容置空
                if(!Bills.isFBFX(parent)|| !project.isInstall()){
                    d.ration_installations = [];
                }
            }
            //计算序列号
            this.calcRationSerialNo(parentID,blockData,updateData,pre,next);
        }else {
             firstParentID = parentID;
             lastNextID = nextID;
          /*  blockData.data.ParentID = parentID;
            blockData.data.NextSiblingID = nextID;*/
            if(pre){
                billUpdate = {type:blockData.datas[0].sourceType,query:{ID:pre.getID()},doc:{NextSiblingID:blockData.datas[0].ID}};
            }
        }
        let dataMap = this.preparePasteData(blockData.datas,billsIDMap,firstParentID,lastNextID,selected);
        if(billUpdate){
            billUpdate.doc.NextSiblingID = billsIDMap[billUpdate.doc.NextSiblingID];
            updateData.push(billUpdate);
        }
        dataMap.updateData = updateData;
        dataMap.projectID = projectObj.project.ID();
        console.log(dataMap);
        $.bootstrapLoading.start();
        CommonAjax.post('/bills/pasteBlock',dataMap,function (result) {
             $.bootstrapLoading.end();
             //更新前端缓存
             me.updateCache(result);
             //插入树节点
             let [rationNodes,calcNodes] = me.addToTree(parentID,nextID,result.bills,result.rations);
             //主材设备工料机插入主树
             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();
                 await itemIncreaseFeeObj.calcItemIncreaseFeeByNodes(rationNodes);
             });
        })

    },

    updateCache:function(result){
        let project = projectObj.project;
        let Bills = project.Bills,Ration = project.Ration;
        let mainTree = project.mainTree;
        Bills.addDatasToList(result.bills);
        Ration.addDatasToList(result.rations);
        Ration.addSubListOfRation(result);//这里是新插入定额时
      /*  project.quantity_detail.addDatasToList(result.quantity_details);
        project.ration_glj.addDatasToList(result.ration_gljs);
        project.ration_coe.addDatasToList(result.ration_coes);
        project.ration_installation.addDatasToList(result.ration_installations);*/
        for(let u of  result.updateData){
            let unode = mainTree.findNode(u.query.ID);
            if(unode){
                for(let ukey in u.doc){
                    unode.data[ukey] = u.doc[ukey];
                }
            }
        }
        //更新项目工料机模块信息-计算消耗量 ---修改了加载方式
      //  project.projectGLJ.datas = result.gljData;
      //  project.projectGLJ.calcQuantity();
        for(let r of result.rations){
            if(r.type == rationType.gljRation){//对于工料机类型的定额，要重新设置下市场单价
                gljOprObj.setGLJPrice(r);
            }
        }
    },

    addToTree:function (parentID,nextID,bills,rations) {
        let project = projectObj.project;
        let Bills = project.Bills,mainTree = project.mainTree;
        let parentNodeMap={};//用于去重
        let parentMap_b = {},parentMap_r = {};
        let newNodes = [],firstNode = null,rationNodes=[],billNodes=[],calcNodes=[];

        createParentMap(parentMap_b,bills,'bills');
        createParentMap(parentMap_r,rations,'ration');
        if(parentMap_b[parentID]){
            for(let i = 0;i < parentMap_b[parentID].length;i++){
                let temNode = loadTreeNode(parentID,nextID,parentMap_b[parentID][i],'bills');
                i==0?firstNode = temNode:'';
            }
        }else if(parentMap_r[parentID]){
            for(let i = 0;i<parentMap_r[parentID].length;i++){
                let temNode =  loadTreeNode(parentID,nextID,parentMap_r[parentID][i],'ration');
                i==0?firstNode = temNode:'';
            }
        }
        ProjectController.syncDisplayNewNodes(projectObj.mainController, newNodes,true);
        let sels = projectObj.mainController.sheet.getSelections();
        //设置选中并更新下方显示
        projectObj.mainController.setTreeSelected(firstNode);
        const serialNo = firstNode.serialNo();
        projectObj.mainController.sheet.setSelection(serialNo, sels[0].col, 1, 1);
        projectObj.mainController.sheet.showRow(serialNo, GC.Spread.Sheets.VerticalPosition.center);
        //没有子节点的清单父节点要进行汇总计算
        for(let b of billNodes){
          if(!b.children || b.children.length == 0){
            if(b.parent &&!parentNodeMap[b.parent.ID]) calcNodes.push(b.parent);
          }  
        }
        return [rationNodes,rationNodes.concat(calcNodes)];

        function loadTreeNode(parentID,nextID,data,type) {
            let newNode = null;
            if(type == 'bills'){
                let newSource = Bills.tree.insertByData(data,parentID,nextID,true);
                newNode = mainTree.insert(parentID, nextID,data.ID);
                if (newNode) {
                    newNode.source = newSource;
                    newNode.sourceType = Bills.getSourceType();
                    newNode.data = data;
                    newNodes.push(newNode);
                    let subType = 'bills';
                    let children = parentMap_b[data.ID];
                    if(!children){
                        children = parentMap_r[data.ID];
                        subType = 'ration';
                    }
                    if(children){
                        for(let c of children){
                            loadTreeNode(data.ID,-1,c,subType);
                        }
                    }

                }
                billNodes.push(newNode);
            }else if(type == 'ration'){
                newNode = project.mainTree.insert(parentID, nextID, data.ID);
                newNode.source = data;
                newNode.sourceType = project.Ration.getSourceType();
                newNode.data = data;
                newNodes.push(newNode);
                rationNodes.push(newNode);
            }
            return newNode;
        }
        
        
        function createParentMap(parentMap,list,type) {
            let parentKey = type=='bills'?'ParentID':'billsItemID';
            for(let l of list){
                let parentID = l[parentKey];
                if(parentMap[parentID]){
                    parentMap[parentID].push(l);
                }else {
                    parentMap[parentID] = [l];
                }
            }
        }

    },

    preparePasteData : function (datas,billsIDMap,firstParentID,lastNextID,selected) {
        let me = this;
        me.datas = _.clone(projectObj.project.Bills.datas);
        let bills = [],rations=[],ration_gljs = [],ration_coes = [],quantity_details = [],ration_installations = [],ration_templates=[];
        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],selected);
        }
        for(let f of firstBillIDs){
            firstIDMap[billsIDMap[f]]  = f //反向映射
        }

        for(let b of bills){//更新ID
            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,ration_templates:ration_templates};

        function eachData(data,selected) {
            if(data.sourceType == 'bills'){
                let tem_b = createBillsData(data,selected);
                bills.push(tem_b);
                for(let d of data.quantity_details){
                    quantity_details.push(createQuantityDetails(d,tem_b,'bills'));
                }
                if(data.children && data.children.length>0){
                    for(let c of data.children){
                        eachData(c, selected);
                    }
                }
            }

            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));
                }
                if(data.ration_template){
                    ration_templates.push(createRationTemplate(data.ration_template,tem_r))
                }
            }

        }

        function createRationTemplate(oldTem,rationData) {
            let template = _.cloneDeep(oldTem);
            delete template._id;
            template.ID = uuid.v1();
            template.projectID = projectObj.project.ID();
            template.rationID = rationData.ID;
            //其它值恢复成默认
            for(let t of template.templateList){
                t.billID = "";
                t.fxID="";
                t.quantity="0";
                t.coe = "";
                if(t.defaultLocation) t.billsLocation = t.defaultLocation;
            }
            return template;
        }
        
        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) {
            let tem_detail = _.cloneDeep(detailData);
            delete tem_detail._id;
            tem_detail.ID = uuid.v1();
            tem_detail.projectID = projectObj.project.ID();
            if(type == 'bills'){
                tem_detail.billID = pdata.ID;
            }
            if(type == 'ration'){
                tem_detail.rationID = pdata.ID;
            }
            return tem_detail;
        }

        function createRationData(rationData) {
            let tem_ration = _.cloneDeep(rationData);
            //删除旧数据
            delete tem_ration._id;
            delete tem_ration.fees;
            delete tem_ration.feesIndex;
            delete tem_ration.ration_gljs;
            delete tem_ration.ration_coes;
            delete tem_ration.ration_installations;
            delete tem_ration.quantity_details;
            delete tem_ration.referenceRationID;//删除关联的主定额信息
            delete tem_ration.__v;
            delete tem_ration.sourceType;
            delete tem_ration.quantityCoe;
            delete tem_ration.rationQuantityCoe;
            delete tem_ration.tenderQuantity;

            tem_ration.projectID = projectObj.project.ID();
            tem_ration.ID = uuid.v1();
            billsIDMap[tem_ration.billsItemID]?tem_ration.billsItemID = billsIDMap[tem_ration.billsItemID]:'';

            let defaultLibID = rationLibObj.getDefaultStdRationLibID();
            if(defaultLibID&&tem_ration.type == rationType.ration){
                tem_ration.prefix = projectObj.project.Ration.getRationPrefix(defaultLibID,tem_ration);
            }
            return tem_ration;

        }

      function createBillsData(billsData, selected) { //ID、重新生成code
            let Bills = projectObj.project.Bills;
            let temData = _.cloneDeep(billsData);
            //删除旧数据
            if(temData.children && temData.children.length>0){//如果是有子项，说明是计算得到的，要删除重新计算，没有子项，但是fees有值，说明是自已输入的，值要一起粘贴
                delete  temData.fees;
                delete  temData.feesIndex;
            }
            delete  temData._id;
            delete  temData.children;
            delete  temData.quantity_details;
            delete  temData.__v;
            delete  temData.sourceType;
            delete  temData.quantityCoe;
            delete temData.rationQuantityCoe;
            //从分项、补项 到清单
            if ((temData.type == billType.FX || temData.type == billType.BX) && !Bills.isFBFX(selected)) temData.type = billType.BILL;
            //从清单到分部分项
            if (temData.type == billType.BILL && Bills.isFBFX(selected)) temData.type = billType.FX;
          
            temData.projectID = projectObj.project.ID();
            let newID = uuid.v1(); //新的清单ID
            billsIDMap[temData.ID] = newID;
            temData.ID = newID; //新的清单ID
            if(temData.code && temData.code.length == 12){//是从清单库来的  //temData.billsLibId && temData.billsLibId!=""    2019-09-03  修改需求，不做清单库ID判断
                let value = temData.code.substr(0,9);
                if (value&&value.length === 9) {//&& /^[\d]+$/.test(value) 去掉全数字判断    07-31 zhang
                    temData.code = me.newFormatCode(value);
                }
            }
            me.datas.push(temData);//为了下一个清单的std code 一样
            return temData;
        }
    },

    calcRationSerialNo:function (billsItemID,blockData,updateData,pre,next) {
        let br = projectObj.project.Ration.getBillsSortRation(billsItemID);
        let firstSerialNo = 0;
        if(next == null){ //没有下一树节点，即为最后节点
            firstSerialNo = br.length > 0 ? br[br.length - 1].serialNo + 1 : 1;
        }else {//有下一节点
            let startIndex =0;
            if(pre){
                startIndex = br.indexOf(pre.data)+1;
            }
            firstSerialNo = br[startIndex].serialNo;
            for(let i = startIndex;i < br.length; i++){
                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.length;i++){
            blockData.datas[i].serialNo = firstSerialNo;
            firstSerialNo += 1;
        }
    },
    calcRationQuantityAndContain : function (billsQuantity,ration,billsUnit) {//计算定额工程量和含量
        let EXPString = ration.quantityEXP+"";
        if(EXPString.indexOf("QDL") != -1){
            if(EXPString=="QDL"){//定额的工程量是直接通过清单量填进来的；
              // 冷姐姐说，克隆、复制整块与插入新定额逻辑分开。前者不管单位直接根据清单数量计算定额工程量。2021-01-12
              // let  t_unit = ration.unit?ration.unit.replace(/^\d+/,""):"";
                // if(t_unit!=billsUnit){//如果定额的单位去除前面的数字后不等于清单单位，定额工程量保持不变
                //     return ;
                // }
                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"));
                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) {
            let s = Number + '';
            while (s.length < 3) {
                s = '0' + s;
            }
            return s;
        };
        for (let i = 0; i <= matchs.length; i++) {
            let formatCode = stdCode + format(i+1);
            if (matchs.indexOf(formatCode) === -1) {
                return formatCode;
            }
        }
    },
    sameStdCode : function (stdCode, filterCode) {
        let reg = new RegExp('^' + stdCode), matchs= [];
        for (let data of this.datas) {
            if (data.code && data.code.length === 12 && reg.test(data.code) && data.code !== filterCode) {
                matchs.push(data.code);
            }
        }
        return matchs;
    },
    isFB :function (selected) {
        return selected.sourceType == projectObj.project.Bills.getSourceType() && selected.data.type == billType.FB;
    },
    isFXorBX:function (selected) {//是分项或者补项
        return projectObj.project.Bills.isFXorBX(selected);
    },
    blockIsFB: function (type) { 
      return type == blockType.FB
    },
    blockIsFXorBX: function (type) {
        return type == blockType.FX||type == blockType.BX;
    },
    blockIsLeaveBills: function (bills) { 
      if (bills.children && bills.children.length > 0) { 
        return bills.children[0].sourceType == "ration" //如果子节点是定额，则说明是页子清单
      }
      return true;
    },
    removeBlock:function () {
        removeLocalCache('project_block');
    }

};