浏览代码

Merge branch 'master' of http://192.168.1.12:3000/SmartCost/ConstructionCost

TonyKang 7 年之前
父节点
当前提交
fe83d8ada7

+ 1 - 0
config/gulpConfig.js

@@ -129,6 +129,7 @@ module.exports = {
         'web/building_saas/report/js/jpc_output.js',
         'web/building_saas/main/js/views/character_content_view.js',
         'web/building_saas/main/js/views/glj_view.js',
+        'web/building_saas/main/js/views/zmhs_view.js',
         'web/building_saas/main/js/views/sub_view.js',
         'web/building_saas/main/js/views/fee_rate_view.js',
         'web/building_saas/main/js/views/sub_fee_rate_views.js',

+ 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);

+ 0 - 1
modules/main/facade/quantity_detail_facade.js

@@ -41,7 +41,6 @@ let updateFunctionMap = {
 }
 
 async function saveQuantityDetail(datas) {
-    console.log(datas);
     let doc = datas;
     doc.ID = uuidV1();
     if(doc.refreshQuantity==false){ //如果选择了不替换工程量,则清空

+ 3 - 1
web/building_saas/complementary_glj_lib/js/gljComponent.js

@@ -4,6 +4,7 @@
 
 let gljComponentOprObj = {
     workBook: null,
+    processDecimal: -6,
     setting: {
         owner: "gljComponent",
         header:[
@@ -498,7 +499,8 @@ let gljComponentOprObj = {
         let me = gljComponentOprObj, gljBasePrc = 0;
         for(let i = 0; i < component.length; i++){
             let roundBasePrc = scMathUtil.roundTo(parseFloat(component[i].basePrice), -2);
-            gljBasePrc = scMathUtil.roundTo(scMathUtil.roundTo(roundBasePrc * parseFloat(component[i].consumeAmt), -2) + gljBasePrc, -2);
+            let roundConsumeAmt = scMathUtil.roundTo(parseFloat(component[i].consumeAmt), -3);
+            gljBasePrc = scMathUtil.roundTo(scMathUtil.roundTo(roundBasePrc * roundConsumeAmt, me.processDecimal) + gljBasePrc, me.processDecimal);
         }
         return gljBasePrc;
     }

+ 7 - 6
web/building_saas/complementary_ration_lib/js/ration_glj.js

@@ -2,6 +2,7 @@
  * Created by Tony on 2017/4/28.
  */
 var rationGLJOprObj = {
+    processDecimal: -6,
     sheet: null,
     currentRationItem: null,
     distTypeTree: null,
@@ -436,29 +437,29 @@ var rationGLJOprObj = {
             if(price.gljType1.length > 0){
                 let labourPrice = 0;
                 price.gljType1.forEach(function (singlePrc) {
-                    labourPrice += singlePrc;
+                    labourPrice = scMathUtil.roundTo(labourPrice + singlePrc, me.processDecimal);
                 });
                 let roundPrice = scMathUtil.roundTo(labourPrice, -2);
                 rst.labourPrice = roundPrice;
-                rationBasePrc += roundPrice;
+                rationBasePrc = scMathUtil.roundTo(rationBasePrc + roundPrice, -2);
             }
             if(price.gljType2.length > 0){
                 let materialPrice = 0;
                 price.gljType2.forEach(function (singlePrc) {
-                    materialPrice += singlePrc;
+                    materialPrice = scMathUtil.roundTo(materialPrice + singlePrc, me.processDecimal);
                 });
                 let roundPrice = scMathUtil.roundTo(materialPrice, -2);
                 rst.materialPrice = roundPrice;
-                rationBasePrc += roundPrice;
+                rationBasePrc = scMathUtil.roundTo(rationBasePrc + roundPrice, -2);
             }
             if(price.gljType3.length > 0){
                 let machinePrice = 0;
                 price.gljType3.forEach(function (singlePrc) {
-                    machinePrice += singlePrc;
+                    machinePrice = scMathUtil.roundTo(machinePrice + singlePrc, me.processDecimal);
                 });
                 let roundPrice = scMathUtil.roundTo(machinePrice, -2);
                 rst.machinePrice = roundPrice;
-                rationBasePrc += roundPrice;
+                rationBasePrc = scMathUtil.roundTo(rationBasePrc + roundPrice, -2);
             }
             rst.rationBasePrc = rationBasePrc;
         }

+ 10 - 2
web/building_saas/main/html/main.html

@@ -111,11 +111,14 @@
                                   <li class="nav-item">
                                       <a class="nav-link active" id="linkGLJ" data-toggle="tab" href="#subSpread" role="tab">人材机</a>
                                   </li>
-                                  <li class="nav-item">
-                                      <a class="nav-link" id="linkFZTJ" data-toggle="tab" href="#subSpread" role="tab">子目换算</a>
+                              <!--    <li class="nav-item">
+                                      <a class="nav-link" id="linkFZTJ" data-toggle="tab" href="#subSpread" role="tab">附注条件</a>
                                   </li>
                                   <li class="nav-item">
                                       <a class="nav-link" id="linkFZDE" data-toggle="tab" href="#subSpread" role="tab">辅助定额</a>
+                                  </li>-->
+                                  <li class="nav-item">
+                                      <a class="nav-link" id="linkZMHS" data-toggle="tab" href="#subSpread" role="tab">子目换算</a>
                                   </li>
                                   <li class="nav-item" id="AZZJF_div" style="display: none">
                                       <a class="nav-link" id="linkAZZJF" data-toggle="tab" href="#subSpread" role="tab">安装增加费</a>
@@ -138,6 +141,10 @@
                                   <div class="tab-pane active" id="subItems" role="tabpanel">
                                       <div class="main-data-bottom ovf-hidden" id="subSpread" style="display: none">
                                       </div>
+                                      <div class="main-data-bottom ovf-hidden" id="tabZMHS" style="display: none">
+                                          <div class=" main-data-bottom ovf-hidden" style="width: 50%; float: left; margin: 0; padding:0;" id="coeSpread"></div>
+                                          <div class=" main-data-bottom ovf-hidden" style="width: 50%; float: left; margin: 0; padding:0;" id="assSpread"></div>
+                                      </div>
                                       <div class="main-data-bottom ovf-hidden" style="display: none" id="comments">
                                           <textarea class="form-control" rows="8" readonly=""></textarea>
                                       </div>
@@ -1239,6 +1246,7 @@
         <script type="text/javascript" src="/web/building_saas/report/js/rpt_print.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/character_content_view.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/glj_view.js"></script>
+        <script type="text/javascript" src="/web/building_saas/main/js/views/zmhs_view.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/sub_view.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/fee_rate_view.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/sub_fee_rate_views.js"></script>

+ 86 - 32
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);
@@ -273,7 +295,7 @@ let BlockController = {
         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)
+        project.ration_installation.addDatasToList(result.ration_installations);
         for(let u of  result.updateData){
             let unode = mainTree.findNode(u.query.ID);
             if(unode){
@@ -296,10 +318,15 @@ let BlockController = {
         createParentMap(parentMap_b,bills,'bills');
         createParentMap(parentMap_r,rations,'ration');
         if(parentMap_b[parentID]){
-            firstNode = loadTreeNode(parentID,nextID,parentMap_b[parentID][0],'bills');
-
+            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]){
-            firstNode = loadTreeNode(parentID,nextID,parentMap_r[parentID][0],'ration');
+            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);
@@ -358,16 +385,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 +532,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.length;i++){
+            blockData.datas[i].serialNo = firstSerialNo;
+            firstSerialNo += 1;
+        }
     },
     calcRationQuantityAndContain : function (billsQuantity,ration) {//计算定额工程量和含量
         let EXPString = ration.quantityEXP+"";

+ 2 - 0
web/building_saas/main/js/main.js

@@ -14,6 +14,7 @@ $(function () {
     mainResizeEles.nav = mainResizeEles.farElement.children('ul.nav');
     loadSize(mainResizeEles, 'height', function() {
         refreshSubSpread();
+        zmhs_obj.refresh();
     });
 
     $("#header-menu").removeAttr('style');
@@ -43,6 +44,7 @@ $(function () {
     slideResize(mainResizeEles, {min: 170, max: 700}, 'height', function() {
         projectObj.mainSpread.refresh();
         refreshSubSpread();
+        zmhs_obj.refresh();
     });
 
     /*const projectId = scUrlUtil.GetQueryString('project');

+ 32 - 11
web/building_saas/main/js/models/calc_program.js

@@ -115,6 +115,9 @@ let calcTools = {
     isNullBill: function (treeNode) {
         return this.isLeafBill(treeNode) && (treeNode.children.length === 0) && (!treeNode.data.calcBase);
     },
+    isCalcBaseBill: function(treeNode){
+        return this.isLeafBill(treeNode) && (treeNode.children.length === 0) && (treeNode.data.calcBase);
+    },
     isTotalCostBill: function (treeNode) {
         return treeNode.data.flagsIndex && treeNode.data.flagsIndex.fixed && treeNode.data.flagsIndex.fixed.flag &&
             treeNode.data.flagsIndex.fixed.flag == fixedFlag.ENGINEERINGCOST;
@@ -131,7 +134,19 @@ let calcTools = {
     isGljRation: function (treeNode) {
         return this.isRationCategory(treeNode) && treeNode.data.type === rationType.gljRation;
     },
-    getGLJList: function (treeNode) {
+    isInheritFrom: function (treeNode, flagsArr){
+        let cur = treeNode;
+        while (cur.parent) {
+            cur = cur.parent;
+        };
+
+        let flag = -1;
+        if (cur.data.flagsIndex && cur.data.flagsIndex.fixed && cur.data.flagsIndex.fixed.flag)
+            flag = cur.data.flagsIndex.fixed.flag;
+
+        return flagsArr.includes(flag);
+    },
+    getGLJList: function (treeNode, needOneBill) {
         delete treeNode.data.gljList;
         if (this.isRationCategory(treeNode)) {
             if (treeNode.data.type != rationType.volumePrice) {
@@ -143,7 +158,7 @@ let calcTools = {
             let q = nodeQ ? nodeQ : 1;
             let rNodes = projectObj.project.Ration.getRationNodes(treeNode);
             let rations = rNodes.map(function (node) {return node.data});
-            treeNode.data.gljList = projectObj.project.ration_glj.getGatherGljArrByRations(rations, q);
+            treeNode.data.gljList = projectObj.project.ration_glj.getGatherGljArrByRations(rations, needOneBill, q);
         };
     },
 
@@ -287,7 +302,7 @@ let calcTools = {
         let nodeQ = me.uiNodeQty(treeNode);
         let isGather = (projectObj.project.property.zanguCalcMode == zanguCalcType.gatherMaterial);
 
-        // 先汇总数量,再乘市场价
+        // 先汇总数量,再乘市场价。如果是叶子清单,进入这里的gljList中的材料,已经是同类材料跨定额汇总过的了。
         function eTFee(){
             if (!treeNode.data.gljList) return 0;
             let GLJObjs = [];
@@ -295,7 +310,8 @@ let calcTools = {
                 if (!allMaterialTypes.includes(glj.type)) continue;
                 if (glj.isEstimate){
                     GLJObjs.push({code: glj.code, name: glj.name, specs: glj.specs, unit: glj.unit, type: glj.type,
-                        quantity: (nodeQ * glj.quantity).toDecimal(decimalObj.process),
+                        // quantity: (nodeQ * glj.quantity).toDecimal(decimalObj.process),
+                        quantity: me.uiGLJQty((glj.totalQuantity)).toDecimal(decimalObj.process),
                         marketPrice: glj.marketPrice});
                 }
                 else{   // 组成物
@@ -305,8 +321,9 @@ let calcTools = {
                     for (let md of mds){
                         if (md.isEstimate){
                             let isExist = false;
-                            let totalQ = (nodeQ * me.uiGLJQty(glj.quantity)).toDecimal(decimalObj.glj.quantity);
-                            let mdQ = (totalQ * me.uiGLJQty(md.consumption)).toDecimal(decimalObj.process);
+                            // let totalQ = (nodeQ * me.uiGLJQty(glj.quantity)).toDecimal(decimalObj.glj.quantity);
+                            let totalQ = me.uiGLJQty((glj.totalQuantity)).toDecimal(decimalObj.glj.quantity);
+                             let mdQ = (totalQ * me.uiGLJQty(md.consumption)).toDecimal(decimalObj.process);
 
                             for (let obj of GLJObjs){
                                 if (gljOprObj.getIndex(md, gljKeyArray) == gljOprObj.getIndex(obj, gljKeyArray)){
@@ -1369,12 +1386,13 @@ class CalcProgram {
             return ['labour', 'material', 'machine', 'mainMaterial', 'equipment'].indexOf(type) > -1;
         };
 
-        // 删掉多余的费用。例如:从其它计算方式切换到公式计算方式,会多出其它的费(不光是common)
+        /*删掉多余的费用。例如:从其它计算方式(有很多费)切换到公式计算方式(只需要common费),多出来的费要删除。
+        fieldNameArr 值取自:遍历treeNode的计算规则,取有绑定的字段名。这些字段名以外的fee是因旧计算多出来的,需要删除。 */
         function deleteUselessFees(treeNode, fieldNameArr){
             if (fieldNameArr){   // 用于计算程序没有绑定的费用类别,不要同步到清单,而清单因为以前计算过该类别又有值,需删除。如切换取费类别,旧费要清掉。
                 for (var i = 0; i < treeNode.data.fees.length; i++) {
                     let fee = treeNode.data.fees[i];
-                    if (!fieldNameArr.includes(fee.fieldName)){
+                    if ((fee.fieldName != 'estimate') && !fieldNameArr.includes(fee.fieldName)){
                         treeNode.data.fees.splice(i, 1);
                         delete treeNode.data.feesIndex[fee.fieldName];
                         treeNode.changed = true;
@@ -1403,7 +1421,7 @@ class CalcProgram {
 
             let nodes = [];
             if (treeNode.calcType == treeNodeCalcType.ctGatherRationsFees){
-                calcTools.getGLJList(treeNode);
+                calcTools.getGLJList(treeNode, true);
                 nodes = me.project.Ration.getRationNodes(treeNode);
             }
             else nodes = treeNode.children;
@@ -1532,7 +1550,7 @@ class CalcProgram {
         // 定额或叶子清单自己的计算程序计算
         else{
             let fnArr = [];
-            calcTools.getGLJList(treeNode);
+            calcTools.getGLJList(treeNode, true);
 
             if (treeNode.calcType == treeNodeCalcType.ctRationCalcProgram) {
                 // 量价、工料机类型的定额要求市场合价
@@ -1579,8 +1597,11 @@ class CalcProgram {
             };
         };
 
-        if (!calcTools.isTotalCostBill(treeNode))  // 已在上面的分支中计算过
+        if (!calcTools.isTotalCostBill(treeNode)){   // 已在上面的分支中计算过
+            calcTools.getGLJList(treeNode, false);
             calcTools.estimateFee(treeNode);
+        }
+
         if (treeNode.changed && !changedArr.includes(treeNode)) changedArr.push(treeNode);
     };
 

+ 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){

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

@@ -128,9 +128,9 @@ const priceTypes = {
 const subSheetIndex = {
     ssiRationGLJ: 0,
     ssiRationCoe: 1,
-    ssiRationAssistant: 2,
+    // ssiRationAssistant: 2,
     ssiQuantityDetail: 3,
-    ssiCalcProgram: 4,
+    ssiCalcProgram: 2,
     ssiMemo: 5,
     ssiFeature: 6
 };

+ 3 - 3
web/building_saas/main/js/models/ration.js

@@ -143,8 +143,8 @@ var Ration = {
 
             function getSubBillsIDs(node) {
                 if (!node) return;
-                if (node.sourceType != sBills) return;
-                if (!node.children || node.children.length == 0 || node.children[0].sourceType != sBills)
+                if (node.sourceType != ModuleNames.bills) return;
+                if (!node.children || node.children.length == 0 || node.children[0].sourceType != ModuleNames.bills)
                     IDs.push(node.data.ID)
                 else
                     getSubBillsIDs(node.children[0]);
@@ -587,7 +587,7 @@ var Ration = {
             billQuantity = parseFloat(billQuantity);
             node.data.contain = contain;
             node.data.quantityEXP="QDL*"+contain;
-            node.data.quantity=scMathUtil.roundForObj(billQuantity*contain,getDecimal("quantity"),node);
+            node.data.quantity=scMathUtil.roundForObj(billQuantity*contain,getDecimal("quantity",node));
             let times = parseInt(node.data.unit)
             if (!isNaN(times)) {
                 node.data.quantityEXP+='*'+times;

+ 4 - 6
web/building_saas/main/js/models/ration_ass.js

@@ -42,8 +42,7 @@ var ration_ass = {
         ration_ass.prototype.refreshAfterUpdate=function(data){
             this.updateRation(data.rationID,data.doc);
             //this.updateRationGLJ(data.ration_glj_list);
-            gljOprObj.assSheetData[data.editIndex].actualValue = data.actualValue;
-            sheetCommonObj.showData(gljOprObj.assSheet,gljOprObj.assSetting,gljOprObj.assSheetData);
+            zmhs_obj.showAssData();
         };
 
         ration_ass.prototype.updateRation = function (rationID,doc) {
@@ -69,10 +68,9 @@ var ration_ass = {
         };
 
         ration_ass.prototype.refreshAfterDelete=function(data){
-            var glj_list = projectObj.project.ration_coe.datas;
-            _.remove(glj_list,data.query);
-            _.remove(gljOprObj.sheetData,data.query);
-            sheetCommonObj.showData(gljOprObj.coeSheet,gljOprObj.coeSetting,gljOprObj.sheetData);
+            var list = projectObj.project.ration_coe.datas;
+            _.remove(list,data.query);
+            zmhs_obj.showAssData();
         };
         ration_ass.prototype.CreateNewAss = function (std) {
             var newAssList = []

+ 3 - 8
web/building_saas/main/js/models/ration_coe.js

@@ -38,9 +38,7 @@ var ration_coe = {
         };
         ration_coe.prototype.refreshAfterSave=function(data){
             projectObj.project.ration_coe.addDatasToList(data);
-            gljOprObj.showCoeData(gljOprObj.coeSheet,gljOprObj.coeSetting,data);
-            gljOprObj.coeSheetData=data;
-            // SheetDataHelper.loadSheetData(setting, rationLibObj.sectionRationsSpread.getActiveSheet(), datas);
+            zmhs_obj.showCoeData();
         };
 
         ration_coe.prototype.addDatasToList = function (datas) {
@@ -65,16 +63,13 @@ var ration_coe = {
             _.forEach(data.doc, function(n, key) {
                 coe_list[coe_index][key] = n;
             });
-
-            var showList = _.filter(coe_list,{'projectID':data.query.projectID,'rationID':coe_list[coe_index].rationID});
-            gljOprObj.coeSheetData=showList;
-            gljOprObj.showCoeData(gljOprObj.coeSheet,gljOprObj.coeSetting,showList);
+            zmhs_obj.showCoeData();
         };
         ration_coe.prototype.refreshAfterDelete=function(data){
             var glj_list = projectObj.project.ration_coe.datas;
             _.remove(glj_list,data.query);
             _.remove(gljOprObj.sheetData,data.query);
-            gljOprObj.showCoeData(gljOprObj.coeSheet,gljOprObj.coeSetting,gljOprObj.sheetData);
+            zmhs_obj.showCoeData();
         };
 
         ration_coe.prototype.getRationCoedata=function(newRation,data){

+ 4 - 1
web/building_saas/main/js/models/ration_glj.js

@@ -56,7 +56,7 @@ var ration_glj = {
             }
         };
 
-        ration_glj.prototype.getGatherGljArrByRations = function (rations, billQuantity) {
+        ration_glj.prototype.getGatherGljArrByRations = function (rations, needOneBill, billQuantity) {
             let result = [];
             let clone = function (obj) {
                 if (obj === null) return null;
@@ -89,6 +89,7 @@ var ration_glj = {
                             result.push(sameGlj);
                         } else {
                             sameGlj.quantity = sameGlj.quantity + (glj.quantity * ration.quantity).toDecimal(4);
+                            sameGlj.totalQuantity = (parseFloat(sameGlj.totalQuantity) + parseFloat(glj.totalQuantity)).toDecimal(4);
                         }
                     }
                 }
@@ -96,6 +97,8 @@ var ration_glj = {
 
             result = gljOprObj.combineWithProjectGlj(result);
 
+            if (!needOneBill) return result;
+
             // 上面取的是清单下所有工料机的总量,我要算清单单价,所以要取单位清单的工料机数量,所以下面要除以清单数量。
             let oneBill = JSON.parse(JSON.stringify(result));
 

+ 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;

文件差异内容过多而无法显示
+ 5 - 357
web/building_saas/main/js/views/glj_view.js


+ 1 - 1
web/building_saas/main/js/views/main_tree_col.js

@@ -83,7 +83,7 @@ let MainTreeCol = {
             return node.data.subType != 201 && node.data.subType != 4 && node.data.subType != 5
         },
         commonUnitFee: function (node) {
-            return true;//!calcTools.isNullBill(node); 设置为只读,有新需求再修改
+            return !(calcTools.isLeafBill(node) && !calcTools.isCalcBaseBill(node) && !calcTools.isInheritFrom(node, [fixedFlag.SUB_ENGINERRING, fixedFlag.MEASURE]));
         },
         //根据节点、父节点类型判断是否可用计算基数
         calcBaseType: function (node) {

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

@@ -415,13 +415,13 @@ var projectObj = {
             else if(fieldName ==='contain'){//编辑含量
                 project.Ration.updateContain(value,node);
             }
-            else if (fieldName === 'quantity' || fieldName === 'marketUnitFee' || fieldName === 'programID' ||
+            else if (fieldName === 'quantity' || fieldName === 'marketUnitFee' || fieldName === 'commonUnitFee' || fieldName === 'programID' ||
                 fieldName === 'subType' || fieldName === 'calcBase' || fieldName === 'isSubcontract'){
                 if (fieldName === 'quantity') {
                     project.quantity_detail.editMainTreeNodeQuantity(value,node,fieldName,editingText);
                     return;
                 }
-                else if (fieldName === 'marketUnitFee') {
+                else if (fieldName === 'marketUnitFee' || fieldName === 'commonUnitFee' ) {
                     if (value) {value = parseFloat(value).toDecimal(decimalObj.decimal("unitPrice", node))};
                 }
                 else if (fieldName === 'calcBase') {
@@ -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)
 

+ 23 - 33
web/building_saas/main/js/views/sub_view.js

@@ -4,12 +4,14 @@
 //modified by zhong on 2017-08-30
 // Tab panes 下有多个Spread时,相互之间不能正确显示。改成一个Spread下多个Sheet。
 //特征及内容spread,解决不能正确显示spread
+
+//zhang 5-31  删除附注条件、辅助定额tab,增加子目换算tab
 contentOprObj.buildSheet($("#jobSpread")[0]);
 characterOprObj.buildSheet($("#itemSpread")[0]);
 $("#tzjnrCon").hide();
 $("#subSpread").show();
-var subSpread = sheetCommonObj.createSpread($("#subSpread")[0], 6);
-subSpread.getSheet(4).name('JSCX');
+var subSpread = sheetCommonObj.createSpread($("#subSpread")[0], 4);
+subSpread.getSheet(2).name('JSCX');
 
 pageCCOprObj.active = false;
 
@@ -19,21 +21,15 @@ gljOprObj.initSheet(subSpread.getSheet(0));
 SheetDataHelper.protectdSheet(subSpread.getSheet(0));
 // assistOprObj.initSheet(subSpread.getSheet(1));
 // sheetCommonObj.shieldAllCells(subSpread.getSheet(1), assistOprObj.setting);
-//附注条件
-gljOprObj.initCoeSheet(subSpread.getSheet(2));
-SheetDataHelper.protectdSheet(subSpread.getSheet(2));
 
-//辅助定额
-gljOprObj.initAssSheet(subSpread.getSheet(1));
-SheetDataHelper.protectdSheet(subSpread.getSheet(1));
 
 //工程量明细
-gljOprObj.initDetailSheet(subSpread.getSheet(3));
-SheetDataHelper.protectdSheet(subSpread.getSheet(3));
+gljOprObj.initDetailSheet(subSpread.getSheet(1));
+SheetDataHelper.protectdSheet(subSpread.getSheet(1));
 
 //安装增加费
-installationFeeObj.initRationInstallSheet(subSpread.getSheet(5));
-SheetDataHelper.protectdSheet(subSpread.getSheet(5));
+installationFeeObj.initRationInstallSheet(subSpread.getSheet(3));
+SheetDataHelper.protectdSheet(subSpread.getSheet(3));
 gljContextMenu.loadGLJSpreadContextMenu();
 
 $("#linkGLJ").click(function(){
@@ -47,23 +43,6 @@ $("#linkGLJ").click(function(){
     //subSpread.getActiveSheet().setValue(0, 0, "工料机");
 });
 
-$("#linkFZDE").click(function(){
-    $("#subItems").children().hide();
-    $("#subSpread").show();
-    pageCCOprObj.active = false;
-    refreshSubSpread();
-    subSpread.setActiveSheetIndex(1);
-    gljOprObj.activeTab='#linkFZDE';
-});
-$("#linkFZTJ").click(function(){
-    $("#subItems").children().hide();
-    $("#subSpread").show();
-    pageCCOprObj.active = false;
-    refreshSubSpread();
-    subSpread.setActiveSheetIndex(2);
-    gljOprObj.activeTab='#linkFZTJ';
-});
-
 
 
 $("#linkAZZJF").click(function(){
@@ -71,7 +50,7 @@ $("#linkAZZJF").click(function(){
     $("#subSpread").show();
     pageCCOprObj.active = false;
     refreshSubSpread();
-    subSpread.setActiveSheetIndex(5);
+    subSpread.setActiveSheetIndex(3);
     gljOprObj.activeTab='#linkAZZJF';
 });
 
@@ -80,7 +59,7 @@ $("#linkGCLMX").click(function(){
     $("#subSpread").show();
     pageCCOprObj.active = false;
     refreshSubSpread();
-    subSpread.setActiveSheetIndex(3);
+    subSpread.setActiveSheetIndex(1);
     gljOprObj.activeTab='#linkGCLMX';
 });
 
@@ -89,8 +68,8 @@ $("#linkJSCX").click(function(){        // 计算程序
     $("#subSpread").show();
     pageCCOprObj.active = false;
     refreshSubSpread();
-    subSpread.setActiveSheetIndex(4);
-    calcProgramObj.initSheet(subSpread.getSheet(4));
+    subSpread.setActiveSheetIndex(2);
+    calcProgramObj.initSheet(subSpread.getSheet(2));
 
     if (!projectObj.mainController.tree.selected)
         projectObj.mainController.tree.selected = projectObj.mainController.tree.firstNode();
@@ -99,6 +78,17 @@ $("#linkJSCX").click(function(){        // 计算程序
     gljOprObj.activeTab='#linkJSCX';
 });
 
+$("#linkZMHS").click(function(){        // 子目换算
+    $("#subItems").children().hide();
+    $("#tabZMHS").show();
+    pageCCOprObj.active = false;
+    refreshSubSpread();
+
+
+    gljOprObj.activeTab='#linkZMHS';
+});
+
+tabZMHS
 //特征及内容
 $("#linkTZJNR").click(function () {
     $("#subItems").children().hide();

+ 384 - 0
web/building_saas/main/js/views/zmhs_view.js

@@ -0,0 +1,384 @@
+/**
+ * Created by zhang on 2018/5/30.
+ */
+
+let zmhs_obj = {
+    coeSpread:null,
+    coeSheet:null,
+    coeSheetData:[],
+    coeSetting: {
+        header: [
+            {headerName: "调整", headerWidth: 100, dataCode: "isAdjust", dataType: "String", cellType: "checkBox"},
+            {headerName: "条件", headerWidth: 120, dataCode: "name", dataType: "String", cellType: "button"},
+            {headerName: "内容", headerWidth: 350, dataCode: "content", dataType: "String", hAlign: "left"}
+        ],
+        view: {
+            lockColumns: [0, 1, 2]
+        }
+    },
+    assSpread:null,
+    assSheet:null,
+    assSheetData: [],
+    assSetting: {
+        header: [
+            {headerName: "调整名称", headerWidth: 100, dataCode: "name", dataType: "String"},
+            {headerName: "定额值", headerWidth: 120, dataCode: "stdValue", hAlign: "right", dataType: "String"},
+            {headerName: "实际值", headerWidth: 120, dataCode: "actualValue", hAlign: "right", dataType: "String"}
+        ],
+        view: {
+            lockColumns: [0, 1]
+        }
+    },
+    initSpread:function () {
+        this.coeSpread = SheetDataHelper.createNewSpread($("#coeSpread")[0]);
+        this.assSpread = SheetDataHelper.createNewSpread($("#assSpread")[0]);
+        this.coeSheet = this.coeSpread.getSheet(0);
+        sheetCommonObj.initSheet(this.coeSheet, this.coeSetting, 30);
+        this.coeSheet.name('ration_coe');
+        this.coeSheet.bind(GC.Spread.Sheets.Events.CellClick, this.onCoeCellClick);
+        this.coeSpread.bind(GC.Spread.Sheets.Events.ButtonClicked, this.onButtonClick);
+        this.coeSheet.bind(GC.Spread.Sheets.Events.EditStarting, function (e,args) {
+            args.cancel = true;
+        });
+        this.assSheet = this.assSpread.getSheet(0);
+        sheetCommonObj.initSheet(this.assSheet, this.assSetting, 30);
+        this.assSheet.bind(GC.Spread.Sheets.Events.EditEnded, this.onAssEditEnded);
+        this.assSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onAssRangeChanged);
+        this.assSheet.name('ration_ass');
+        SheetDataHelper.protectdSheet(this.coeSheet);
+    },
+    showCoeData:function (node) {
+        let selected = node?node:projectObj.project.mainTree.selected;
+        let ration_coe = projectObj.project.ration_coe;
+        let coeList = [];
+        if(selected&&selected.sourceType == "ration"){
+            let ration = selected.data;
+            coeList = ration_coe.getCoeByRationID(ration.ID);
+        }
+        sheetCommonObj.showData(this.coeSheet, this.coeSetting,coeList);
+        this.coeSheet.floatingObjects.remove("customerCoe");
+        if (coeList.length > 0) {
+            var cus_index = _.findIndex(coeList, function (item) {
+                return item.coeID == -1;
+            })
+            if (cus_index != -1) {
+                this.addDropDownList();
+                this.addCusButton(cus_index, 1, coeList[cus_index].name);
+            }
+        }
+        this.coeSheetData = coeList;
+
+    },
+    showAssData:function (node) {
+        let selected = node?node:projectObj.project.mainTree.selected;
+        let assList = selected&&selected.data.rationAssList ? selected.data.rationAssList : [];
+        this.assSheet.setRowCount(0);
+        sheetCommonObj.showData(this.assSheet, this.assSetting, assList);
+        this.assSheetData = assList;
+        this.assSheet.getRange(assList.length,-1,this.assSheet.getRowCount()-assList.length, -1, GC.Spread.Sheets.SheetArea.viewport).locked(true);
+
+    },
+    refresh:function () {
+        this.coeSpread?this.coeSpread.refresh():'';
+        this.assSpread?this.assSpread.refresh():'';
+    },
+    showZMHSData:function (node) {
+        if(this.coeSpread&& this.assSpread){
+            this.showCoeData(node);
+            this.showAssData(node);
+            //hide floatingObject
+            var floatingObject = this.coeSheet.floatingObjects.get('customerCoe');
+            if (floatingObject) {
+                floatingObject.isVisible(false);
+            }
+        }
+    },
+    onCoeCellClick: function (sender, args) {
+        let me = zmhs_obj;
+        let floatingObject = me.coeSheet.floatingObjects.get('customerCoe');
+        if(floatingObject){
+            let isVisable = floatingObject.isVisible();
+            if (isVisable) {
+                let result = me.checkIfNeedUpdate();
+                if (result.isNeed) {
+                    projectObj.project.ration_coe.updateCustomerCoe(result);
+                }
+                floatingObject.isVisible(false);
+            }
+        }
+
+    },
+    onButtonClick:function (sender, args) {
+        let me = zmhs_obj;
+        let sheet = args.sheet, row = args.row, col = args.col;
+        let cellType = sheet.getCellType(row, col);
+        if(args.sheet.isEditing()){
+            args.sheet.endEdit();
+        }
+        if (cellType instanceof GC.Spread.Sheets.CellTypes.Button) {
+            if(args.sheetName == 'ration_coe'){
+                me.onCusButtonClick(sender, args);
+            }
+        } else {
+            me.onCoeCheckBoxClick(sender, args)
+        }
+    },
+    onCusButtonClick: function (sender, args) {
+        var me = zmhs_obj;
+        var floatingObject = me.coeSheet.floatingObjects.get('customerCoe');
+        var isVisable = floatingObject.isVisible();
+        if (!isVisable) {
+            me.coeSheet.getCell(args.row, args.col, GC.Spread.Sheets.SheetArea.viewport).locked(false);
+            me.showFloationObject(floatingObject, me.coeSheetData[args.row]);
+        } else {
+            var result = me.checkIfNeedUpdate();
+            if (result.isNeed) {
+                projectObj.project.ration_coe.updateCustomerCoe(result);
+            }
+            floatingObject.isVisible(false);
+        }
+    },
+    showFloationObject(floatingObject, data){
+        floatingObject.isVisible(true);
+        var sheet = this.coeSheet;
+        var startRow = this.coeSheetData.length;
+        var endRow = startRow + 7;
+        floatingObject.startRow(startRow);
+        floatingObject.startColumn(1);
+        floatingObject.endColumn(2);
+        floatingObject.endRow(endRow);
+        this.bindFloadingObjectValue(data);
+        sheet.repaint();
+    },
+    bindFloadingObjectValue(data){
+        $('#coe_ration').val(data.coes[0].amount);
+        $('#manual').val(data.coes[1].amount);
+        $('#material').val(data.coes[2].amount);
+        $('#manchine').val(data.coes[3].amount);
+        $('#mainM').val(data.coes[4].amount);
+        $('#equipment').val(data.coes[5].amount);
+    },
+    onInputChange(id, name){
+        var coe = _.find(zmhs_obj.coeSheetData, function (c) {
+            return c.coeID == -1;
+        });
+        var newValue = zmhs_obj.numberValueChecking($('#' + id).val());
+        if (newValue) {
+            newValue = _.round(newValue, 2);
+            if (newValue == coe.coes[name].amount) return;
+            if (id == 'coe_ration') {
+                $('#coe_ration').val(newValue);
+                $('#manual').val(newValue);
+                $('#material').val(newValue);
+                $('#manchine').val(newValue);
+                $('#mainM').val(newValue);
+                $('#equipment').val(newValue);
+            } else {
+                $('#' + id).val(newValue);
+            }
+        } else {
+            $('#' + id).val(coe.coes[name].amount);
+        }
+    },
+    checkIfNeedUpdate(){
+        var data = _.find(zmhs_obj.coeSheetData, function (c) {
+            return c.coeID == -1;
+        });
+        var result = {
+            isNeed: false
+        }
+        var coe_ration = $('#coe_ration').val();
+        var manual = $('#manual').val();
+        var material = $('#material').val();
+        var manchine = $('#manchine').val();
+        var mainM = $('#mainM').val();
+        var equipment = $('#equipment').val();
+        if (coe_ration != data.coes[0].amount) {
+            result.isNeed = true;
+            data.coes[0].amount = coe_ration;
+        }
+        if (manual != data.coes[1].amount) {
+            result.isNeed = true;
+            data.coes[1].amount = manual;
+        }
+        if (material != data.coes[2].amount) {
+            result.isNeed = true;
+            data.coes[2].amount = material;
+        }
+        if (manchine != data.coes[3].amount) {
+            result.isNeed = true;
+            data.coes[3].amount = manchine;
+        }
+        if (mainM != data.coes[4].amount) {
+            result.isNeed = true;
+            data.coes[4].amount = mainM;
+        }
+        if (equipment != data.coes[5].amount) {
+            result.isNeed = true;
+            data.coes[5].amount = equipment;
+        }
+        if (result.isNeed) {
+            result.doc = {
+                coes: data.coes
+            };
+            result.query = {
+                projectID: data.projectID,
+                ID: data.ID,
+                rationID: data.rationID
+            };
+        }
+        return result;
+
+    },
+    numberValueChecking: function (val) {
+        var newval = Number(val);
+        if (number_util.isNumber(newval)) {
+            return newval;
+        } else {
+            if (val) {
+                alert('您输入的数据类型不正确,请重新输入。');
+            }
+            newval = null;
+        }
+        return newval;
+    },
+    onCoeCheckBoxClick:function (sender, args) {
+        let me = zmhs_obj;
+        let checkboxValue = args.sheet.getCell(args.row, args.col).value();
+        let newval = 0;
+        if (checkboxValue) {
+            newval = 0;
+            args.sheet.getCell(args.row, args.col).value(newval);
+        } else {
+            newval = 1;
+            args.sheet.getCell(args.row, args.col).value(newval);
+        }
+        let recode = me.coeSheetData[args.row];
+        projectObj.project.ration_coe.adjustCoeClick(recode, newval);
+    },
+    addCusButton: function (row, col, text) {
+        var cus_button = new GC.Spread.Sheets.CellTypes.Button();
+        zmhs_obj.coeSheet.setCellType(row, col, cus_button, GC.Spread.Sheets.SheetArea.viewport);
+        cus_button.marginLeft(0);
+        cus_button.marginTop(0);
+        cus_button.marginRight(0);
+        cus_button.marginBottom(0);
+        cus_button.text(text);
+        cus_button.buttonBackColor('white');
+        zmhs_obj.coeSheet.repaint();
+    },
+    addDropDownList: function () {
+        var sheet = this.coeSheet;
+        sheet.suspendPaint();
+        var customFloatingObject = new GC.Spread.Sheets.FloatingObjects.FloatingObject("customerCoe");
+        var div = document.createElement('div');
+        div.innerHTML = this.generateHtmlString();
+        customFloatingObject.startRow(1);
+        customFloatingObject.startColumn(1);
+        customFloatingObject.endColumn(2);
+        customFloatingObject.endRow(2);
+        $(div).css('background', 'white');
+        customFloatingObject.content(div);
+        sheet.floatingObjects.add(customFloatingObject);
+        customFloatingObject.isVisible(false);
+        sheet.resumePaint();
+    },
+    generateHtmlString: function () {
+        var newString = "<form ><table border='1px' bordercolor='#CCCCCC' cellspacing='0px' style='border-collapse:collapse;font-size: 10px;>";
+        newString += this.getOneRow('定额', 0, 'coe_ration');
+        newString += this.getOneRow('人工', 1, 'manual');
+        newString += this.getOneRow('材料', 2, 'material');
+        newString += this.getOneRow('机械', 3, 'manchine');
+        newString += this.getOneRow('主材', 4, 'mainM');
+        newString += this.getOneRow('设备', 5, 'equipment');
+        newString += "</table></form>";
+        return newString;
+    },
+    getOneRow: function (text, name, id) {
+        var rowstr = "<tr style='height:10px'><td style='width: 50px'>" + text
+            + ":</td><td style='width: 70px' align='right'><input type='text'value='1' name=" + name
+            + " style='width:30px;border:0;height:14px' align='right' id=" + id + " onchange='zmhs_obj.onInputChange(this.id,this.name)'></td></tr>";
+        return rowstr;
+
+    },
+    onAssEditEnded:function (e,args) {
+        var me = zmhs_obj;
+        if (args.row >= me.assSheetData.length) {
+            me.assSheet.getCell(args.row, args.col).value(null);
+            return;
+        }
+        if (me.assSetting.header[args.col].dataCode == 'actualValue') {//实际值
+            me.updateRationAss(args);
+        }
+    },
+    onAssRangeChanged:function (e,args) {
+        let me = zmhs_obj;
+        if (args.action == GC.Spread.Sheets.RangeChangedAction.clear) {
+            args.editingText = null;
+        }else if(args.action == GC.Spread.Sheets.RangeChangedAction.paste){
+            args.editingText = args.sheet.getCell(args.row,args.col).value();
+        }
+        if (args.sheetName == 'ration_ass') {
+            me.updateRationAss(args);
+        }
+
+    },
+    updateRationAss: function (args) {
+        var me = zmhs_obj;
+        var newval;
+        newval = me.numberValueChecking(args.editingText);
+        var recode = me.assSheetData[args.row];
+        if (args.editingText === null) {
+            newval = parseFloat(recode.stdValue);
+        }
+        var isValidate = false;
+        if (newval) {
+            isValidate = me.checkingActualValue(recode, newval)
+        }
+        if (isValidate) {
+            newval = scMathUtil.roundTo(newval, -2);
+            projectObj.project.ration_ass.updateActualValue(me.assSheetData, args.row, newval)
+        } else {
+            newval = recode.actualValue;
+            me.assSheet.getCell(args.row, args.col).value(newval);
+        }
+    },
+    checkingActualValue(record, newval){
+        let minExist = record.minValue && record.minValue != '0' ? true : false;
+        let maxExist = record.maxValue && record.maxValue != '0' ? true : false;
+        let minValue = parseFloat(record.minValue);
+        let maxValue = parseFloat(record.maxValue);
+
+        if (!maxExist && minExist) {
+            if (newval < minValue) {
+                alert('实际值应≥' + minValue);
+                return false;
+            }
+        }
+        if (maxExist && !minExist) {
+            if (newval > maxValue) {
+                alert('实际值应≤' + maxValue);
+                return false;
+            }
+        }
+        if (maxExist && minExist) {
+            if (newval < minValue || newval > maxValue) {
+                alert('实际值应介于' + minValue + '~' + maxValue + '之间');
+                return false;
+            }
+        }
+        return true;
+    }
+
+};
+
+
+$(function () {
+    $('#linkZMHS').on('shown.bs.tab', function (e) {
+        if(zmhs_obj.coeSpread == null || zmhs_obj.assSpread == null){
+            zmhs_obj.initSpread();
+        }
+        zmhs_obj.refresh();
+        zmhs_obj.showZMHSData();
+    })
+});

+ 1 - 1
web/building_saas/pm/js/pm_newMain.js

@@ -1944,7 +1944,7 @@ function getAddTenderFile(tenderName, selected, options){
     //非新建
     else{
         rst.id = selected.val();
-        rst.name =  selected.text();
+        rst.name =  selected.children("option:selected").text();
     }
     return rst;
 }