/** * Created by zhang on 2018/5/10. */ let BlockController = { datas:[], 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)){//除了复制定额外,焦点行和复制的块不是来自同一个地方(分部分项工其它) 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) { if(node.data.calcBase ==null||node.data.calcBase ==undefined|| node.data.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;i0){ 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(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) { 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); 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 = me.addToTree(parentID,nextID,result.bills,result.rations); //主材设备工料机插入主树 project.ration_glj.addToMainTree(result.ration_gljs); //更新计算程序模板,并进行重新计算 project.calcProgram.calcNodesAndSave(rationNodes,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 parentMap_b = {},parentMap_r = {}; let newNodes = [],firstNode = null,rationNodes=[]; 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;i0){ for(let c of data.children){ eachData(c); } } } 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; 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) { //ID、重新生成code 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; 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"){//定额的工程量是直接通过清单量填进来的; 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); }, blockIsFXorBX: function (type) { return type == blockType.FX||type == blockType.BX; }, removeBlock:function () { removeLocalCache('project_block'); } };