Explorar o código

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

vian %!s(int64=4) %!d(string=hai) anos
pai
achega
bbad578c2d

+ 1 - 1
web/building_saas/fee_rates/fee_rate.html

@@ -17,7 +17,7 @@
             </div>
         </div>
         <div class="col-lg-4 p-0">
-            <div class="form-inline py-1" style="margin-top: 5px"><input type="checkbox" id="cascadeSet" checked >  <label class="mx-2" >统一设置相同参数</label></div>
+            <div class="form-inline py-1" style="margin-top: 5px; display:none"><input type="checkbox" id="cascadeSet" checked >  <label class="mx-2" >统一设置相同参数</label></div>
         </div>
     </div>
 </div>

+ 25 - 0
web/building_saas/main/js/models/fee_rate.js

@@ -53,6 +53,31 @@ var FeeRate = {
             var rates = this.getActivateFeeRate().rates;
             return _.find(rates,{'ID':ID})
         };
+        FeeRate.prototype.getAllSubRates = function (trates) {
+
+            let rates = trates ? trates : this.getActivateFeeRate().rates;
+            let subRates = [],
+              nameMap = {},
+              temRates = [];
+            for (let r of rates) {
+              if (gljUtil.isDef(r.subFeeRate)) {
+                for (let p of r.subFeeRate.recodes) {
+                  if (nameMap[p.name] == true) continue;
+                  nameMap[p.name] = true;
+                  subRates.push(p);
+                  if (p.subList && p.subList.length > 0) {
+                    for (let sub of p.subList) {
+                      sub.isSub = true;
+                      sub.ParentID = p.ID;
+                      subRates.push(sub);
+                    }
+                  }
+                }
+              }
+            }
+            return _.sortByAll(subRates, ['ID']) //要保证树节点的ID子项是紧跟着父项的,不然的话显示会有问题
+        };
+
         FeeRate.prototype.getSubViewData= function(item) {
             var datas = [];
             if(item.hasOwnProperty('subFeeRate')&&item.subFeeRate!=undefined){

+ 7 - 7
web/building_saas/main/js/models/project.js

@@ -567,7 +567,7 @@ var PROJECT = {
             let refreshNode = [];
             let reclacQuantity = false;
             let deleteNode=[],addNodeDatas=[];
-            let changeParentIDMap = {};
+           // let changeParentIDMap = {}; 确定刷新无错后删除
             for(let d of datas){
                 let temObj = null;
                 if(d.type == ModuleNames.bills || d.type == ModuleNames.ration){//如果是树节点类型,直接取树节点更新
@@ -590,7 +590,7 @@ var PROJECT = {
                                 if(gljUtil.isDef(d.data.quantity))reclacQuantity = true;
                                 refreshNode.push(temNode);
                                 if(d.data.ParentID){//更新了父节点-相当于删了再添加
-                                    changeParentIDMap[temNode.data.ParentID] = true;
+                                    //changeParentIDMap[temNode.data.ParentID] = true;
                                    deleteNode.push(temNode);
                                    this.updateParentNode(temNode,d.data.ParentID,addNodeDatas);
                                 } 
@@ -629,27 +629,27 @@ var PROJECT = {
                 addNewNodes(rationsDatas,refreshNode);
             });
 
-            for(let pID in changeParentIDMap){
+        /*     for(let pID in changeParentIDMap){
               let pnode =  this.mainTree.getNodeByID(pID);
               getNextRefreshNode(pnode,refreshNode);
-            }
+            } */
 
             if(reclacQuantity) this.projectGLJ.calcQuantity();
             return refreshNode;
 
 
-            function getNextRefreshNode(node,refreshNode){
+         /*    function getNextRefreshNode(node,refreshNode){
                 if(node.nextSibling){
                     refreshNode.push(node.nextSibling)
                     getNextRefreshNode(node.nextSibling,refreshNode)
                 } 
-            };
+            }; */
 
             function deleteTreeNodes(deleteNodes) {
                 let controller = projectObj.mainController, project = projectObj.project;
                 let Bill = project.Bills, Ration = project.Ration;
                 for(let rd of deleteNodes){
-                    controller.sheet.deleteRows(rd.serialNo(),rd.posterityCount + 1);
+                    controller.sheet.deleteRows(rd.serialNo(),rd.posterityCount() + 1);
                     controller.tree.delete(rd);
                     if(rd.sourceType == Bill.getSourceType()) Bill.tree.delete(rd.source);
                 }

+ 2 - 1
web/building_saas/main/js/models/ration.js

@@ -540,9 +540,10 @@ var Ration = {
             }
         };
         ration.prototype.insertVolumePrice = function(type,ext){
+            let isEmpty = ext?false:true;
             this.addNewRation(null,rationType.volumePrice,function (newNode) {//插入人工不需要自动定位到编号列
                 projectObj.selectColAndFocus(newNode,null);
-            },true,type,true,ext);
+            },isEmpty,type,true,ext);
         };
         // 已经有数据,更新前端缓存及节点,不进行通信
         ration.prototype.addNewDataSimply = function (newData) {

+ 104 - 1
web/building_saas/main/js/views/fee_rate_view.js

@@ -567,7 +567,7 @@ 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.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;
@@ -713,6 +713,108 @@ var feeRateObject={
             projectObj.project.FeeRate.batchUpdateFeeRate([{rateIndex:selected.row,rate:item}],feeRateObject.activateFeeRate);
         }
     },
+    setRateFromSub:function (subRate,value,subList,editText,feeRateCoe) {//editText  下拉框选择的值,对于如“19.00”这样下拉选择项,value会变成19,所以在valueMap里找的时候要用editText去查找
+        let me = feeRateObject,feeRate =  projectObj.project.FeeRate;
+        let rates = feeRate.getActivateFeeRate().rates;
+        let updateDatas = [];
+        //对于有子节点的记录和可输入的记录,只支持一个参数(因为还要内插法取费率值),如果要支持两个以上的参数,valueMap要再改下~~~~
+        for(let r of rates){
+            if(gljUtil.isDef(r.subFeeRate)){
+                let valueArray=[];//用来存参数的值 //这里和养护的不一样,这里下拉框是{text:value}的形式,那里是直接下匹配
+                let temP =null;//这个用来存储需要内插法记算的时候,同时,树节点的子节点改变也计在这里, 这样,改变temP的值,会体现在保存subRecode
+                let match = false;
+                let temR = _.cloneDeep(r);//临时存储
+                for(let p of temR.subFeeRate.recodes){
+                    if(p.name == subRate.name){
+                        temP = p;
+                        match = true;
+                    }
+                    let setValue = false;
+                    for(let o of p.optionList){
+                        if(match == true) {//匹配上了,改对应的selected 为 true
+                            if(o.value == value){//这里和养护的不一样,这里下拉框是{text:value}的形式,那里是直接下匹配
+                                o.selected = true;
+                                valueArray.push(value);
+                                setValue = true;
+                            }else {
+                                o.selected = false;
+                            }
+                        }else {//没有匹配上的,直接取值就可以(这个是为多参数时用的,但是目前来看,不支持多参数,比较麻烦)
+                            if(o.selected == true)  valueArray.push(o.value);
+                        }
+                    }
+                    if(match==true && setValue ==false) valueArray.push(value);//如果匹配上了,但是setValue为false,说明没有满足和选项,要用内插法或超出倍数算值
+                }
+                if(match == true){//说明要改rate的值,先从valueMap中去查
+                    if(subList && temP.subList && temP.subList.length > 0){
+                        temP.subList = subList;// 设置树节点的子节点的值
+                    }
+                    let doc = {"subFeeRate":temR.subFeeRate};
+                    let valueKey = valueArray.join('-');
+                    let valueMaps = r.subFeeRate.valueMaps;
+                    if(me.feeRateSpecialHandle){//不同编办特殊处理
+                        let sf = me.feeRateSpecialHandle(subRate,value);
+                        if(!_.isEmpty(sf)){
+                            valueKey = sf.valueKey;
+                            temP.value = sf.value;
+                        }
+                    }
+                    let rate = _.find(valueMaps,{"ID":valueKey});
+                    if(isDef(rate)) {//找到了,直接改费率值
+                        doc.rate = rate.value;
+                    } else {//没找到,用内插法或步长算值
+                        let ltRate = null;//
+                        let gtRate = null;
+                        temP.value = scMathUtil.roundForObj(value,getDecimal("feeRate")) ;
+                        for(let v of valueMaps){
+                           if(parseFloat(v.ID)<parseFloat(value)){
+                               ltRate = v;
+                           }else if( gtRate==null && parseFloat(v.ID)>parseFloat(value)){
+                               gtRate = v;
+                           }
+                        }
+                        if(gljUtil.isDef(ltRate)&&gljUtil.isDef(gtRate)){//已经找到前后的值了
+                            let step = scMathUtil.roundForObj(gtRate.value - ltRate.value,getDecimal("process"));
+                            let total =  parseFloat(gtRate.ID) - parseFloat(ltRate.ID)
+                            doc.rate =getRateByStep(ltRate.value,total,parseFloat(value) - parseFloat(ltRate.ID),step);
+                        }else if(gljUtil.isDef(ltRate)&&gtRate == null){//说明是超出了选项的最大值
+                            let share = parseFloat(value) - parseFloat(ltRate.ID);//超出了多少
+                            doc.rate = getRateByStep(ltRate.value,temP.step,share,temP.amount)
+                        }else if(gljUtil.isDef(gtRate)&&ltRate==null){//说明是只有一个选项,且这个选项比输入的值大
+                            let step =  parseFloat(gtRate.value)- 0;
+                            doc.rate = getRateByStep(0,gtRate.value,value,step)
+                        }
+                    }
+                    if(isDef(doc.rate)){
+                        if(feeRateCoe) doc.rate = scMathUtil.roundForObj(doc.rate * feeRateCoe,getDecimal("feeRate"));    //如果是从乘系数过来的,乘以系数。
+                        updateDatas.push({rateID:r.ID,doc:doc});
+                    }
+                }
+            }
+        }
+       if(updateDatas.length > 0){
+           $.bootstrapLoading.start();
+           feeRate.updateFeeRatesByIDs(updateDatas,async function () {
+               let feerateInfo = [];
+               for(let u of updateDatas){
+                   feerateInfo.push({rateID:u.rateID,value:u.doc["rate"]});
+               }
+               subRateObject.showSubRateData();
+               me.showMainFeeRateData();
+               if(feerateInfo.length > 0){
+                   await feeRate.onFeeRatesChange(feerateInfo);
+               }else {
+                   $.bootstrapLoading.end();
+               }
+           })
+       }
+       function getRateByStep(ltValue,total,share,step) { //min值 ,计算值的总区间, 区间中占比,步长--后端重选标准也要用到
+           let p = scMathUtil.roundForObj(share/total,getDecimal("process"));
+           let a = scMathUtil.roundForObj(step * p,getDecimal("process")) ;
+           return scMathUtil.roundForObj(ltValue + a,getDecimal("feeRate"))
+       }
+   },
+
     cascadeSetRates:function(selectedItem,sourceRow,mapID,selectMap){
         let items=[];
         items.push({rateIndex:sourceRow,rate:selectedItem});
@@ -1048,6 +1150,7 @@ $(function(){
         let me = feeRateObject;
         $(e.relatedTarget.hash).removeClass('active');
         if(me.mainFeeRateSpread == null)  me.initFeeRateSpread(0);
+        subRateObject.initSubRateSpread();
         me.showMainFeeRateData();
         me.loadPageContent();
     });

+ 88 - 3
web/building_saas/main/js/views/sub_fee_rate_views.js

@@ -92,8 +92,11 @@ var subRateObject={
             //this.subRateSheet.bind(GC.Spread.Sheets.Events.ValueChanged, me.onSheetValueChange);
             this.subRateSheet.name('subRateSheet');
         }
+      /* 20201209 改成和公路一样 
         subRateObject.datas = projectObj.project.FeeRate.getSubViewData(item);
-        subRateObject.valueMap=projectObj.project.FeeRate.getValueMap(item);
+        subRateObject.valueMap=projectObj.project.FeeRate.getValueMap(item); 
+        
+        */
         subRateObject.showSubRateData();
         disableRightMenu("subRate",this.subRateSpread);
         if(projectReadOnly){
@@ -103,17 +106,50 @@ var subRateObject={
             sheetCommonObj.disableSpread(this.subRateSpread);
         }
     },
+  /*  20201209 改成和公路一样 
+   showSubRateData:function () {
+        this.subRateSheet.setRowCount(0);
+        sheetCommonObj.showData(this.subRateSheet, this.subRateSetting, this.datas);
+        this.subRateSheet.setRowCount(this.datas.length);
+        for(let row =0; row < this.datas.length;row++){
+            this.setComboOptionCell(row,1,this.datas[row],this.subRateSheet);
+        }
+    }, */
+
     showSubRateData:function () {
+        let preSelections = this.subRateSheet.getSelections();
+        this.datas = projectObj.project.FeeRate.getAllSubRates();
         this.subRateSheet.setRowCount(0);
         sheetCommonObj.showData(this.subRateSheet, this.subRateSetting, this.datas);
         this.subRateSheet.setRowCount(this.datas.length);
+        let parentMap=_.groupBy(this.datas, 'ParentID');
+        let visibleMap = {};
+        this.subRateSheet.suspendPaint();
+        this.subRateSheet.suspendEvent();
         for(let row =0; row < this.datas.length;row++){
             this.setComboOptionCell(row,1,this.datas[row],this.subRateSheet);
+            this.setTreeNodeCellType(this.datas,row,parentMap,visibleMap,this.subRateSheet);
+        }
+        this.subRateSheet.resumeEvent();
+        this.subRateSheet.resumePaint();
+        if(preSelections){//定位光标到之前的位置
+            this.subRateSheet.setSelection(preSelections[0].row,preSelections[0].col,preSelections[0].rowCount,preSelections[0].colCount);
         }
     },
     onSubRateSelectChanged:function (e,info) {
         info.sheet.repaint();
     },
+    setTreeNodeCellType:function (datas,row,parentMap,visibleMap,sheet) {
+        delete parentMap.undefined;//去掉无用节点
+        let treeNode = sheetCommonObj.getTreeNodeCellType(datas,row,parentMap);
+        treeNode.treeNodeType = false;
+        if((datas[row].subList && datas[row].subList.length >0)||datas[row].isSub == true ){
+            treeNode.treeNodeType = true;
+            visibleMap[datas[row].ID] = treeNode.collapsed;
+        }
+        sheet.setCellType(row, 0, treeNode, GC.Spread.Sheets.SheetArea.viewport);
+        if(visibleMap[datas[row].ParentID]) sheet.getRange(row , -1, 1, -1).visible(!visibleMap[datas[row].ParentID]);//显示或隐藏
+    },
     setComboOptionCell:function(row,col,subRate,sheet){
         let options=[];
         for(let op of subRate.optionList){
@@ -153,7 +189,9 @@ var subRateObject={
             feeRateObject.updateBySelect(rate,selectMap,mapID);
         }
     },
-    onSubRateValueChange:function (e,info) {
+/*   
+    20201209 改成和公路一样 
+onSubRateValueChange:function (e,info) {
         console.info(info);
         let me = subRateObject, selectValueList=[],selectMap={};
         if(me.datas&&me.datas.length>0){
@@ -171,7 +209,54 @@ var subRateObject={
             feeRateObject.updateBySelect(rate,selectMap,mapID);
         }
     },
-
+ */
+    onSubRateValueChange:function (e,info,feeRateCoe) {
+        let me = subRateObject, subList=null;
+        let value = info.newValue;
+        let subRate = me.datas[info.row];
+        if(subRate.editable == true || subRate.isSub == true){//是可编辑的,要检查数据类型
+            let checkResult = scMathUtil.isNumOrFormula(value);
+            if(checkResult!=null && !isNaN(checkResult)){
+                value = scMathUtil.roundForObj(checkResult,getDecimal("feeRate"));
+            }else {
+                alert('当前输入的数据类型不正确,请重新输入。');
+                return me.showSubRateData();
+            }
+        }
+        if(subRate.isSub == true){//是树节点的子节点,计算父节点的值
+            let parentRate = _.find(me.datas,{"ID":subRate.ParentID});//找到父节点
+            if(parentRate){
+                let sum = 0;
+                subList = _.cloneDeep(parentRate.subList);
+                for(let s of subList){//按比例计算
+                    if(s.ID == subRate.ID) s.value = value;//当前项要用新输入的值
+                    let v_a = scMathUtil.roundForObj(s.value * s.amount,getDecimal("process"))
+                    sum = scMathUtil.roundForObj(sum + v_a,getDecimal("feeRate"));
+                }
+                value = sum;
+                subRate = parentRate;//把subRate 指向parentRate
+            }
+        } else if(subRate.subList && subRate.subList.length > 0){//输入树节结的父结点,子结点都等于父节点的值
+            subList = _.cloneDeep(subRate.subList);
+            for(let t of subList){
+                t.value = value
+            }
+        }
+        if(me.timeStamp = null){
+            me.timeStamp =  +new Date()
+            feeRateObject.setRateFromSub(subRate,value,subList,info.newValue,feeRateCoe);
+        }else {
+            let now = +new Date();
+            if(now - me.timeStamp < 500){
+                setTimeout(function () {
+                    feeRateObject.setRateFromSub(subRate,value,subList,info.newValue,feeRateCoe);
+                },500)
+            }else {
+                feeRateObject.setRateFromSub(subRate,value,subList,info.newValue,feeRateCoe);
+            }
+            me.timeStamp = now;
+        }
+    },
     destorySpreadView:function () {
         if(this.views){
             this.views.destroy();