Selaa lähdekoodia

子费率树结构

zhangweicheng 7 vuotta sitten
vanhempi
commit
672653b3ba

+ 13 - 0
modules/all_models/fee_rates.js

@@ -12,9 +12,21 @@ let optionSchema = new Schema({
     selected:Boolean
 },{versionKey:false,_id: false})
 
+let subRecord = new Schema({
+    ID:Number,
+    name:String,
+    amount: Number,//倍数
+    value: Number,
+}, {_id: false});
+
 let recordSchema = new Schema({
     ID:Number,
     name:String,
+    editable:Boolean,
+    step: Number,//每增加的步数
+    amount: Number,//倍数
+    value: Number,
+    subList:[subRecord],
     optionList:[optionSchema]
 },{versionKey:false,_id: false})
 
@@ -34,6 +46,7 @@ let ratesSchema = new Schema({
     name: String,
     rate: Number,
     memo: String,
+    sum:Boolean,
     subFeeRate:subFeeRatesSchema
 },{versionKey:false,_id: false});
 

+ 131 - 0
public/web/sheet/sheet_common.js

@@ -686,7 +686,138 @@ var sheetCommonObj = {
         }
         return new getTipsCombo();
     },
+    getTreeNodeCellType:function (datas,row,parentMap) {// 2018-09-26  不用spreadjs默认的树结构,自定义控件
+        var ns = GC.Spread.Sheets;
+        let rectW = 10;
+        let rectH = 10;
+        let margin = 3;
 
+        function TreeNodeCellType() {
+            this.collapsed = gljUtil.isDef(datas[row].collapsed)?datas[row].collapsed: true; //默认是折叠的
+            this. treeNodeType = true;
+            this.rectInfo = {};
+        }
+        TreeNodeCellType.prototype = new ns.CellTypes.Text();
+        TreeNodeCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
+            let offset = 0;
+            let step = 7;
+            let level = getTreeLevel(datas[row],datas);//从0开始,取当前节点是第几级的
+            let tem = offset+margin+ rectW/2+step;//两条线之间的间隔
+            let t_offset = offset;
+            let temParentID = datas[row].ParentID;
+            if(this.treeNodeType == true){
+                for(let i = level;i>0;i--){//这里是画子节点前面的竖线,从第二级开始
+                    let temParent = getParent(temParentID,datas);
+                    if(temParent){//父节点有下一个兄弟节点才需要画
+                        if(hasNextBrother(parentMap,temParent)) sheetCommonObj.drawLine(ctx,x+t_offset+tem*i,y,x+t_offset+tem*i,y+h);
+                        temParentID = temParent.ParentID;
+                    }
+                    offset +=tem;
+                }
+            }
+            offset+=step; //这个没法移动,所以要两个判断
+            if(this.treeNodeType == true){
+                if(hasChildern(datas[row].ID,datas)){//如果是有子节点
+                    //第一条 或者没有父节点(如费率子表综合里程项)不用画方框头上那条竖线其它都要
+                    if(row !=0 && gljUtil.isDef(datas[row].ParentID)) sheetCommonObj.drawLine(ctx,x+offset+ rectW/2+margin,y,x+offset+ rectW/2+margin,y + Math.round(h / 2) - rectH / 2);
+                    //画方框下面的那条竖线,如果没有下一个兄弟节点,则不用画
+                    if(hasNextBrother(parentMap,datas[row])) sheetCommonObj.drawLine(ctx,x+offset+ rectW/2+margin,y + Math.round(h / 2) + rectH / 2,x+offset+ rectW/2+margin,y + h);
+                    sheetCommonObj.drowRect(ctx, x+offset, y, w, h,rectW,rectH,margin);
+                    sheetCommonObj.drowSymbol(ctx, x+offset, y, w, h,rectW,rectH,margin, this.collapsed);
+                    this.rectInfo = {x:x+offset+margin,rectW:rectW}//计录一下可点击位置
+                }else {
+                    let hasNext = datas[row+1]?datas[row+1].ParentID == datas[row].ParentID:false;
+                    sheetCommonObj.drowSubItem(ctx, x, y, w, h, offset,hasNext,margin+ rectW/2);
+                }
+            }
+            offset += step;
+            offset += rectW;
+            x = x + offset;//设置偏移
+            w = w - offset;
+            GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
+        };
+        // override getHitInfo to allow cell type get mouse messages
+        TreeNodeCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
+            return {
+                x: x,
+                y: y,
+                row: context.row,
+                col: context.col,
+                cellStyle: cellStyle,
+                cellRect: cellRect,
+                sheetArea: context.sheetArea
+            };
+        }
+        TreeNodeCellType.prototype.processMouseDown = function (hitinfo) {
+            if (!_.isEmpty(this.rectInfo)&&hitinfo.x < this.rectInfo.x+this.rectInfo.rectW && hitinfo.x > this.rectInfo.x) {
+                this.collapsed = !this.collapsed;
+                datas[row].collapsed = this.collapsed;
+                this.refreshChildrenVisible(hitinfo.sheet);
+                hitinfo.sheet.invalidateLayout();
+                hitinfo.sheet.repaint();
+            }
+        };
+        TreeNodeCellType.prototype.refreshChildrenVisible = function (sheet) {
+            sheet.suspendPaint();
+            sheet.suspendEvent();
+            refreshVisible(datas[row]);
+            sheet.resumeEvent();
+            sheet.resumePaint();
+            function refreshVisible(item){
+                if(parentMap[item.ID]){
+                    for(let sub of parentMap[item.ID]){
+                        refreshVisible(sub)
+                    }
+                }
+                let visible = getVisible(item);
+                let trow = datas.indexOf(item);
+                sheet.getRange(trow , -1, 1, -1).visible(visible);
+            }
+
+            function getVisible(item) {
+                if(item.ParentID){
+                    let parent = getParent(item.ParentID,datas);
+                    if(!parent) return true;
+                    let p_row= datas.indexOf(parent);
+                    let visible = !sheet.getCellType(p_row,0).collapsed;
+                    if(visible == true){ //如果是显示的,则要再往父节点的父节点检查,只要有一个节点是隐藏的,则都是隐藏
+                        return getVisible(parent);
+                    }else {
+                        return visible
+                    }
+                }else {//如果parentID 为空则是最根节点
+                    return true;
+                }
+            }
+
+
+        };
+        return new TreeNodeCellType()
+
+        function getTreeLevel(item,data) {
+            if(item.ParentID){
+                let pitem =  _.find(data,{'ID':item.ParentID});
+                return  getTreeLevel(pitem,data) + 1;
+            }else {
+                return 0
+            }
+        }
+        function hasChildern(ID,data) {//返回是否有子项
+            let p = _.find(data,{'ParentID':ID});
+            if(p) return true;
+            return false
+        }
+        function getParent(ParentID,data) {
+            let p = _.find(data,{'ID':ParentID});
+            return p;
+        }
+        function hasNextBrother(parentMap,item){
+            let children =parentMap[item.ParentID];
+            if(!gljUtil.isDef(children)|| children.indexOf(item) == children.length -1) return false;
+            return true
+        }
+
+    },
     setDynamicCombo: function (sheet, beginRow, col, rowCount, items, itemsHeight, itemsType) {
         let me = this;
         sheet.suspendPaint();

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

@@ -2017,6 +2017,8 @@
     <script type="text/javascript" src="/web/building_saas/main/js/views/glj_col.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/main_tree_col.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/project_info.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/project_glj_view.js'></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/project_view.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/options_view.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/project_property_bills_quantity_decimal.js"></script>
@@ -2041,7 +2043,6 @@
     <script type="text/javascript" src='/web/building_saas/main/js/views/confirm_modal.js'></script>
     <script type="text/javascript" src='/web/building_saas/main/js/views/zlfb_view.js'></script>
     <script type="text/javascript" src='/web/building_saas/main/js/views/installation_fee_view.js'></script>
-    <script type="text/javascript" src='/web/building_saas/main/js/views/project_glj_view.js'></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/importBills.js"></script>
     <!--报表-->
     <script type="text/javascript" src="/public/web/rpt_tpl_def.js"></script>
@@ -2060,7 +2061,6 @@
     <script type="text/javascript" src="/web/building_saas/main/js/views/tender_price_view.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/billsElf.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/quantity_edit_view.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/sub_fee_rate_views.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/calc_base_view.js"></script>

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

@@ -53,6 +53,33 @@ var FeeRate = {
             var rates = this.getActivateFeeRate().rates;
             return _.find(rates,{'ID':ID})
         };
+        FeeRate.prototype.getChildrenByID = function (ID) {
+          ID = parseInt(ID);
+          let rates = this.getActivateFeeRate().rates;
+          return _.filter(rates,{'ParentID':ID});
+        };
+        FeeRate.prototype.getAllSubRates = function () {
+            let rates =  this.getActivateFeeRate().rates;
+            let subRates = [],nameMap={};
+            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 subRates;
+        };
         FeeRate.prototype.getSubViewData= function(item) {
             var datas = [];
             if(item.hasOwnProperty('subFeeRate')&&item.subFeeRate!=undefined){

+ 41 - 134
web/building_saas/main/js/views/fee_rate_view.js

@@ -170,10 +170,10 @@ var feeRateObject={
                 }
                 sheet.setValue(row, col, val, ch);
                 if(col==0){
-                    let treeType = feeRateObject.getTreeNodeCellType(data,row,parentMap);
+                    let treeType = sheetCommonObj.getTreeNodeCellType(data,row,parentMap);
                     sheet.getCell(row, 0).cellType(treeType);
                     visibleMap[data[row].ID] = treeType.collapsed;
-                    if(visibleMap[data[row].ParentID] ) sheet.getRange(row , -1, 1, -1).visible(false);//显示或隐藏
+                    if(visibleMap[data[row].ParentID] ) sheet.getRange(row , -1, 1, -1).visible(!visibleMap[data[row].ParentID]);//显示或隐藏
                 }
             }
         }
@@ -246,131 +246,6 @@ var feeRateObject={
 
         }
     },
-    getTreeNodeCellType:function (datas,row,parentMap) {// 2018-09-26  不用spreadjs默认的树结构,自定义控件
-        var ns = GC.Spread.Sheets;
-        let rectW = 10;
-        let rectH = 10;
-        let margin = 3;
-        function TreeNodeCellType() {
-            this.collapsed = true; //默认是折叠的
-            this.rectInfo = {};
-        }
-        TreeNodeCellType.prototype = new ns.CellTypes.Text();
-        TreeNodeCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
-            let offset = 0;
-            let step = 7;
-            let level = getTreeLevel(datas[row],datas);//从0开始,取当前节点是第几级的
-            let tem = offset+margin+ rectW/2+step;//两条线之间的间隔
-            let t_offset = offset;
-            let temParentID = datas[row].ParentID;
-            for(let i = level;i>0;i--){//这里是画子节点前面的竖线,从第二级开始
-                let temParent = getParent(temParentID,datas);
-                if(temParent){//父节点有下一个兄弟节点才需要画
-                    if(hasNextBrother(parentMap,temParent)) sheetCommonObj.drawLine(ctx,x+t_offset+tem*i,y,x+t_offset+tem*i,y+h);
-                    temParentID = temParent.ParentID;
-                }
-                offset +=tem;
-            }
-            offset+=step;
-            if(hasChildern(datas[row].ID,datas)){//如果是有子节点
-                //第一条不用画方框头上那条竖线其它都要
-                if(row !=0) sheetCommonObj.drawLine(ctx,x+offset+ rectW/2+margin,y,x+offset+ rectW/2+margin,y + Math.round(h / 2) - rectH / 2);
-                //画方框下面的那条竖线,如果没有下一个兄弟节点,则不用画
-               if(hasNextBrother(parentMap,datas[row])) sheetCommonObj.drawLine(ctx,x+offset+ rectW/2+margin,y + Math.round(h / 2) + rectH / 2,x+offset+ rectW/2+margin,y + h);
-                sheetCommonObj.drowRect(ctx, x+offset, y, w, h,rectW,rectH,margin);
-                sheetCommonObj.drowSymbol(ctx, x+offset, y, w, h,rectW,rectH,margin, this.collapsed);
-                this.rectInfo = {x:x+offset+margin,rectW:rectW}//计录一下可点击位置
-            }else {
-                let hasNext = datas[row+1]?datas[row+1].ParentID == datas[row].ParentID:false;
-                sheetCommonObj.drowSubItem(ctx, x, y, w, h, offset,hasNext,margin+ rectW/2);
-            }
-            offset += step;
-            offset += rectW;
-            x = x + offset;//设置偏移
-            w = w - offset;
-            GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
-        };
-        // override getHitInfo to allow cell type get mouse messages
-        TreeNodeCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
-            return {
-                x: x,
-                y: y,
-                row: context.row,
-                col: context.col,
-                cellStyle: cellStyle,
-                cellRect: cellRect,
-                sheetArea: context.sheetArea
-            };
-        }
-        TreeNodeCellType.prototype.processMouseDown = function (hitinfo) {
-            if (!_.isEmpty(this.rectInfo)&&hitinfo.x < this.rectInfo.x+this.rectInfo.rectW && hitinfo.x > this.rectInfo.x) {
-                this.collapsed = !this.collapsed;
-                this.refreshChildrenVisible(hitinfo.sheet);
-                hitinfo.sheet.invalidateLayout();
-                hitinfo.sheet.repaint();
-            }
-        };
-        TreeNodeCellType.prototype.refreshChildrenVisible = function (sheet) {
-            sheet.suspendPaint();
-            sheet.suspendEvent();
-            refreshVisible(datas[row]);
-            sheet.resumeEvent();
-            sheet.resumePaint();
-            function refreshVisible(item){
-                if(parentMap[item.ID]){
-                    for(let sub of parentMap[item.ID]){
-                        refreshVisible(sub)
-                    }
-                }
-                let visible = getVisible(item);
-                let trow = datas.indexOf(item);
-                sheet.getRange(trow , -1, 1, -1).visible(visible);
-            }
-            
-            function getVisible(item) {
-                if(item.ParentID){
-                    let parent = getParent(item.ParentID,datas);
-                    if(!parent) return true;
-                    let p_row= datas.indexOf(parent);
-                    let visible = !sheet.getCellType(p_row,0).collapsed;
-                    if(visible == true){ //如果是显示的,则要再往父节点的父节点检查,只要有一个节点是隐藏的,则都是隐藏
-                        return getVisible(parent);
-                    }else {
-                        return visible
-                    }
-                }else {//如果parentID 为空则是最根节点
-                    return true;
-                }
-            }
-            
-            
-        };
-        return new TreeNodeCellType()
-
-        function getTreeLevel(item,data) {
-            if(item.ParentID){
-                 let pitem =  _.find(data,{'ID':item.ParentID});
-                 return  getTreeLevel(pitem,data) + 1;
-             }else {
-                 return 0
-             }
-         }
-        function hasChildern(ID,data) {//返回是否有子项
-             let p = _.find(data,{'ParentID':ID});
-             if(p) return true;
-             return false
-         }
-        function getParent(ParentID,data) {
-             let p = _.find(data,{'ID':ParentID});
-             return p;
-         }
-        function hasNextBrother(parentMap,item){
-            let children =parentMap[item.ParentID];
-            if(children && children.indexOf(item) == children.length -1) return false;
-            return true
-        }
-
-    },
     getFeeRateEditCellType:function () {
         var ns = GC.Spread.Sheets;
         function FeeRateEditCellType() {
@@ -519,7 +394,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;
@@ -559,7 +434,7 @@ var feeRateObject={
         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){//有子节点时不能编辑费率列
+        if(dataCode=="rate"&&(recode.sum != true && me.getChildrenCount(recode.ID,me.mainFeeRateData)>0)){//除了标记要汇总的节点,其它的有子节点时不能编辑费率列
             return false;
         }
         return true;
@@ -581,7 +456,34 @@ var feeRateObject={
         }
         me.updateFeerateWhenCellsChange(changeCells);
     },
+    sumParentRate:function (rateID,value,updateDatas) {
+        let feeRate = projectObj.project.FeeRate;
+        let rate = feeRate.getFeeRateByID(rateID);
+        let parent = feeRate.getFeeRateByID(rate.ParentID);
+        if(parent && parent.sum == true){
+            let suRates = feeRate.getChildrenByID(parent.ID);
+            let total = 0;
+            for(let r of suRates) {
+                let tem = r.rate ? r.rate:0;
+                tem = scMathUtil.roundForObj(tem,getDecimal("feeRate"));
+                if (rateID == r.ID){
+                    tem = value;
+                }else {
+                    let u = _.find(updateDatas,{"rateID":r.ID})//看是不是更新的过程中包含了汇总的数据
+                    if(u && gljUtil.isDef(u.doc.rate)) tem = u.doc.rate;
+                }
+                total = scMathUtil.roundForObj(tem + total,getDecimal('process'))
+            }
+            total = scMathUtil.roundForObj(total,getDecimal("feeRate"));
+            let tp =  _.find(updateDatas,{"rateID":parent.ID});//如果父节点也在更新列表中
+            if(tp){
+                tp.doc.rate = total
+            }else {
+                updateDatas.push({rateID:parent.ID,doc:{rate:total}});
+            }
+        }
 
+    },
     updateFeerateWhenCellsChange:function (cells) {// col,row,newValue
         let me = feeRateObject,updateDatas = [],feeRate = projectObj.project.FeeRate;//[{rateID:rateID,doc:doc}]
         let refreshA = [];//记录刷新条数的数组
@@ -609,16 +511,20 @@ var feeRateObject={
             }
             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(fieldID == 'rate') feeRateObject.sumParentRate(recode.ID,value,updateDatas);
         }
         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});
+                for(let u of updateDatas){
+                    let row = _.findIndex(me.mainFeeRateData,{'ID':u.rateID})
+                    for(let key in u.doc){
+                        let col = _.findIndex(me.mainFeeRateSetting.header,{'dataCode':key});
+                        me.mainFeeRateSheet.setValue(row, col, u.doc[key]);
+                        if(key == 'rate'){
+                            feerateInfo.push({rateID:u.rateID,value:u.doc[key]});
+                        }
                     }
                 }
                 feerateInfo.length > 0 ?feeRate.onFeeRatesChange(feerateInfo):'';
@@ -995,6 +901,7 @@ $(function(){
         let me = feeRateObject;
         $(e.relatedTarget.hash).removeClass('active');
         if(me.mainFeeRateSpread == null)  me.initFeeRateSpread(0);
+        subRateObject.initSubRateSpread();
         me.showMainFeeRateData();
         me.loadPageContent();
     });

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

@@ -986,7 +986,7 @@ var projectObj = {
                 projectObj.refreshMainSpread();
                 //定位到会话中的选项
                 let mainTabFocus = sessionStorage.getItem('mainTab') ? sessionStorage.getItem('mainTab') : '#tab_zaojiashu';
-                $(`${mainTabFocus}`).click();
+                $(mainTabFocus).click();
                 if(projectReadOnly){
                     disableSpread(that.mainSpread);
                 }

+ 28 - 6
web/building_saas/main/js/views/sub_fee_rate_views.js

@@ -11,7 +11,7 @@ var subRateObject={
     subRateSheet:null,
     subRateSetting:{
         header: [
-            {headerName: "参数名称", headerWidth: 110, dataCode: "name", dataType: "String"},
+            {headerName: "参数名称", headerWidth: 160, dataCode: "name", dataType: "String"},
             {headerName: "参数值", headerWidth: 150, dataCode: "optionValue", dataType: "String",getText:'forOption'}
         ],
         view: {
@@ -19,8 +19,9 @@ var subRateObject={
         },
         getText:{
             forOption:function (item,val) {
+                if(item.isSub == true) return item.value;//可编辑子节点
                 let o = _.find(item.optionList,{'selected':true});
-                return o?o.value:'';
+                return o?o.name:'';
             }
         }
     },
@@ -92,8 +93,8 @@ var subRateObject={
             //this.subRateSheet.bind(GC.Spread.Sheets.Events.ValueChanged, me.onSheetValueChange);
             this.subRateSheet.name('subRateSheet');
         }
-        subRateObject.datas = projectObj.project.FeeRate.getSubViewData(item);
-        subRateObject.valueMap=projectObj.project.FeeRate.getValueMap(item);
+        subRateObject.datas = projectObj.project.FeeRate.getAllSubRates();
+        //subRateObject.valueMap=projectObj.project.FeeRate.getValueMap(item);
         subRateObject.showSubRateData();
         disableRightMenu("subRate",this.subRateSpread);
         if(projectReadOnly){
@@ -107,21 +108,42 @@ var subRateObject={
         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();
     },
     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=[];
+        if(subRate.isSub == true) return;//是树节点的子节点;
         for(let op of subRate.optionList){
-            options.push({text:op.name,value:op.value});
+            //options.push({text:op.name,value:op.value});
+            options.push(op.name);
         }
         let dynamicCombo = sheetCommonObj.getDynamicCombo();//new GC.Spread.Sheets.CellTypes.ComboBox();
         dynamicCombo.items(options);
-        dynamicCombo.editorValueType(GC.Spread.Sheets.CellTypes.EditorValueType.value);
+        if(subRate.editable == true) dynamicCombo.editable(true);
+        //dynamicCombo.editorValueType(GC.Spread.Sheets.CellTypes.EditorValueType.value);
         sheet.setCellType(row, col, dynamicCombo, GC.Spread.Sheets.SheetArea.viewport);
     },
     addComboboxOption:function (datas) {