Browse Source

Merge branch 'master' of http://smartcost.f3322.net:3000/SmartCost/ConstructionCost

zhongzewei 7 years ago
parent
commit
a0c6342db8

+ 4 - 5
public/calc_util.js

@@ -238,7 +238,6 @@ class Calculation {
         me.compiledFeeTypeNames = [];
         me.compiledFeeTypeNames = [];
         me.compiledCalcBases = {};
         me.compiledCalcBases = {};
         me.saveForReports = [];
         me.saveForReports = [];
-        me.changed = false;
 
 
         let private_compile_feeRateFile = function() {
         let private_compile_feeRateFile = function() {
             if (feeRates) {
             if (feeRates) {
@@ -400,7 +399,7 @@ class Calculation {
             if (!$treeNode.data.fees) {
             if (!$treeNode.data.fees) {
                 $treeNode.data.fees = [];
                 $treeNode.data.fees = [];
                 $treeNode.data.feesIndex = {};
                 $treeNode.data.feesIndex = {};
-                me.changed = true;
+                $treeNode.changed = true;
             };
             };
 
 
             for (let idx of template.compiledSeq) {
             for (let idx of template.compiledSeq) {
@@ -427,17 +426,17 @@ class Calculation {
                         };
                         };
                         $treeNode.data.fees.push(fee);
                         $treeNode.data.fees.push(fee);
                         $treeNode.data.feesIndex[calcItem.fieldName] = fee;
                         $treeNode.data.feesIndex[calcItem.fieldName] = fee;
-                        me.changed = true;
+                        $treeNode.changed = true;
                     }
                     }
                     else{
                     else{
                         if ($treeNode.data.feesIndex[calcItem.fieldName].unitFee != calcItem.unitFee){
                         if ($treeNode.data.feesIndex[calcItem.fieldName].unitFee != calcItem.unitFee){
                             $treeNode.data.feesIndex[calcItem.fieldName].unitFee = calcItem.unitFee;
                             $treeNode.data.feesIndex[calcItem.fieldName].unitFee = calcItem.unitFee;
-                            me.changed = true;
+                            $treeNode.changed = true;
                         };
                         };
 
 
                         if ($treeNode.data.feesIndex[calcItem.fieldName].totalFee != calcItem.totalFee){
                         if ($treeNode.data.feesIndex[calcItem.fieldName].totalFee != calcItem.totalFee){
                             $treeNode.data.feesIndex[calcItem.fieldName].totalFee = calcItem.totalFee;
                             $treeNode.data.feesIndex[calcItem.fieldName].totalFee = calcItem.totalFee;
-                            me.changed = true;
+                            $treeNode.changed = true;
                         };
                         };
                     }
                     }
                 };
                 };

+ 10 - 0
public/web/sheet/sheet_data_helper.js

@@ -280,5 +280,15 @@ var SheetDataHelper = {
             sheet.setSelection(range.row, range.col, range.rowCount, range.colCount);
             sheet.setSelection(range.row, range.col, range.rowCount, range.colCount);
         }
         }
         return target;
         return target;
+    },
+    /**
+     * 在sheet中使用delete键,触发EndEdited事件
+     * @param sheet
+     */
+    deleteBind: function (sheet, fun) {
+        sheet.addKeyMap(46, false, false, false, false, function () {
+            let selections = sheet.getSelections();
+            
+        });
     }
     }
 };
 };

+ 7 - 1
web/building_saas/main/js/calc/bills_calc.js

@@ -323,6 +323,12 @@ class BillsCalcHelper {
             this.setTotalFee(node, field, value, isIncre);
             this.setTotalFee(node, field, value, isIncre);
         }
         }
     };
     };
+    clearFeeFields(node, fields, isIncre) {
+        for (let field of fields) {
+            node.data.feesIndex[field.type].unitFee = 0;
+            this.setTotalFee(node, field, 0, isIncre);
+        }
+    }
     calcNode(node, isIncre) {
     calcNode(node, isIncre) {
         if (node.source.children.length > 0) {
         if (node.source.children.length > 0) {
             this.calcParent(node, this.project.calcFields, isIncre);
             this.calcParent(node, this.project.calcFields, isIncre);
@@ -334,7 +340,7 @@ class BillsCalcHelper {
                     this.calcVolumePriceLeaf(node, this.project.calcFields, isIncre);
                     this.calcVolumePriceLeaf(node, this.project.calcFields, isIncre);
                 }
                 }
             } else {
             } else {
-
+                this.clearFeeFields(node, this.project.calcFields, isIncre);
             }
             }
         }
         }
     };
     };

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

@@ -5,10 +5,103 @@
  *  用到费率的规则必须有feeRateID属性,当有该属性时,会自动显示费率值。
  *  用到费率的规则必须有feeRateID属性,当有该属性时,会自动显示费率值。
  */
  */
 
 
+let billDefaultTemplate = [
+    {
+        ID: 1,
+        serialNo: '一',
+        code: "A",
+        name: "定额直接费",
+        dispExpr: "A1+A2+A3",
+        statement: "人工费+材料费+机械费",
+        feeRate: null,
+        type: 'RationDirect',
+        memo: ''
+    },
+    {
+        ID: 2,
+        serialNo: '1',
+        code: "A1",
+        name: "人工费",
+        dispExpr: "H_J",
+        statement: "合计",
+        feeRate: 0,
+        type: 'labour',
+        memo: ''
+    },
+    {
+        ID: 3,
+        serialNo: '2',
+        code: "A2",
+        name: "材料费",
+        dispExpr: "H_J",
+        statement: "合计",
+        feeRate: 100,
+        type: 'material',
+        memo: ''
+    },
+    {
+        ID: 4,
+        serialNo: '3',
+        code: "A3",
+        name: "机械费",
+        dispExpr: "H_J",
+        statement: "合计",
+        feeRate: 0,
+        type: 'machine',
+        memo: ''
+    },
+    {
+        ID: 5,
+        serialNo: '二',
+        code: "A4",
+        name: "管理费",
+        dispExpr: "A",
+        statement: "定额直接费",
+        feeRate: 0,
+        type: 'management',
+        memo: ''
+    },
+    {
+        ID: 6,
+        serialNo: '三',
+        code: "B",
+        name: "利润",
+        dispExpr: "A",
+        statement: "定额直接费",
+        feeRate: 0,
+        type: 'profit',
+        memo: ''
+    },
+    {
+        ID: 7,
+        serialNo: '四',
+        code: "C",
+        name: "风险费用",
+        dispExpr: "",
+        statement: "",
+        feeRate: null,
+        type: 'risk',
+        memo: ''
+    },
+    {
+        ID: 8,
+        serialNo: '',
+        code: "",
+        name: "综合单价",
+        dispExpr: "A+B",
+        statement: "定额直接费+利润",
+        feeRate: NaN,
+        type: 'common',
+        memo: ''
+    }
+];
+
 class CalcProgram {
 class CalcProgram {
     constructor(project){
     constructor(project){
         this.project = project;
         this.project = project;
         this.datas = [];
         this.datas = [];
+        this.digit = 2;
+        this.digitDefault = 6;
         this.calc = new Calculation();
         this.calc = new Calculation();
         project.registerModule(ModuleNames.calc_program, this);
         project.registerModule(ModuleNames.calc_program, this);
     };
     };
@@ -50,6 +143,7 @@ class CalcProgram {
     };
     };
 
 
     calculate(treeNode){
     calculate(treeNode){
+        let me = this;
         if (treeNode.sourceType === this.project.Ration.getSourceType()) {
         if (treeNode.sourceType === this.project.Ration.getSourceType()) {
             treeNode.data.gljList = this.project.ration_glj.getGljArrByRation(treeNode.data.ID);
             treeNode.data.gljList = this.project.ration_glj.getGljArrByRation(treeNode.data.ID);
         }
         }
@@ -61,19 +155,155 @@ class CalcProgram {
         this.calc.calculate(treeNode);
         this.calc.calculate(treeNode);
 
 
         // 存储、刷新本结点、所有父结点
         // 存储、刷新本结点、所有父结点
-        if (this.calc.changed){
-            let data = {ID: treeNode.data.ID, projectID: projectObj.project.ID(), fees: treeNode.data.fees};
-            let newDta = {'updateType': 'ut_update', 'updateData': data};
-            let newDataArr = [];
-            newDataArr.push(newDta);
-            projectObj.project.pushNow('', treeNode.sourceType, newDataArr);
-            projectObj.mainController.refreshTreeNode([treeNode]);
-
-            if (treeNode.parent) {
-                projectObj.converseCalculateBills(treeNode.parent);
+        if (treeNode.changed) {
+            me.saveAndCalcParents(treeNode);
+            delete treeNode.changed;
+        };
+
+    };
+
+    saveAndCalcParents(treeNode) {
+        if (treeNode.parent) {
+            projectObj.converseCalculateBills(treeNode.parent);
+        };
+
+        let data = {ID: treeNode.data.ID, projectID: projectObj.project.ID(), fees: treeNode.data.fees};
+        let newDta = {'updateType': 'ut_update', 'updateData': data};
+        let newDataArr = [];
+        newDataArr.push(newDta);
+        projectObj.project.pushNow('', treeNode.sourceType, newDataArr);
+        projectObj.mainController.refreshTreeNode([treeNode]);
+    };
+
+    initFees(treeNode){
+        if (!treeNode.data.fees) {
+            treeNode.data.fees = [];
+            treeNode.data.feesIndex = {};
+            treeNode.changed = true;
+        };
+    };
+
+    checkFee(treeNode, ftObj){
+        if (!treeNode.data.feesIndex[ftObj.type]){
+            let fee = {
+                'fieldName': ftObj.type,
+                'unitFee': ftObj.unitFee,
+                'totalFee': ftObj.totalFee,
+                'tenderUnitFee': 0,
+                'tenderTotalFee': 0
+            };
+            treeNode.data.fees.push(fee);
+            treeNode.data.feesIndex[ftObj.type] = fee;
+            treeNode.changed = true;
+        }
+        else{
+            if (treeNode.data.feesIndex[ftObj.type].unitFee != ftObj.unitFee){
+                treeNode.data.feesIndex[ftObj.type].unitFee = ftObj.unitFee;
+                treeNode.changed = true;
+            };
+
+            if (treeNode.data.feesIndex[ftObj.type].totalFee != ftObj.totalFee){
+                treeNode.data.feesIndex[ftObj.type].totalFee = ftObj.totalFee;
+                treeNode.changed = true;
+            };
+        };
+    };
+
+    gatherFeeTypes(treeNode, gatherType){
+        let me = this;
+        let rst = [];
+
+        if (treeNode.sourceType === this.project.Bills.getSourceType()) {
+            me.initFees(treeNode);
+
+            let objsArr = [];
+            if (gatherType == CP_GatherType.rations){
+                objsArr = this.project.Ration.getRationsByNode(treeNode);
+            }else if (gatherType == CP_GatherType.bills){
+                objsArr = treeNode.children;
+            };
+
+            for (let ft of feeType) {
+                let ftObj = {};
+                ftObj.type = ft.type;
+                ftObj.name = ft.name;
+                let uf = 0, tf = 0, tuf = 0, ttf = 0;
+                for (let item of objsArr) {
+                    let data = {};
+                    if (gatherType == CP_GatherType.rations){
+                        data = item;
+                    }else if (gatherType == CP_GatherType.bills){
+                        data = item.data;
+                    };
+                    if (data.feesIndex && data.feesIndex[ft.type]) {
+                        uf = (uf + parseFloat(data.feesIndex[ft.type].unitFee)).toDecimal(me.digitDefault);
+                        tf = (tf + parseFloat(data.feesIndex[ft.type].totalFee)).toDecimal(me.digitDefault);
+                        tuf = (tuf + parseFloat(data.feesIndex[ft.type].tenderUnitFee)).toDecimal(me.digitDefault);
+                        ttf = (ttf + parseFloat(data.feesIndex[ft.type].tenderTotalFee)).toDecimal(me.digitDefault);
+                    };
+                };
+                ftObj.unitFee = uf.toDecimal(me.digit);
+                ftObj.totalFee = tf.toDecimal(me.digit);
+                ftObj.tenderUnitFee = tuf.toDecimal(me.digit);
+                ftObj.tenderTotalFee = ttf.toDecimal(me.digit);
+
+                me.checkFee(treeNode, ftObj);
+
+                rst.push(ftObj);
+            };
+
+            if (treeNode.changed) {
+                me.saveAndCalcParents(treeNode);
+                delete treeNode.changed;
+            };
+        };
+
+        return rst;
+    };
+
+    getCalcDatas(treeNode){
+        let me = this;
+        let rst = [];
+        let isRation = treeNode.sourceType === me.project.Ration.getSourceType();
+        let isBill = treeNode.sourceType === me.project.Bills.getSourceType();
+        let isLeafBill = isBill && treeNode.source.children && treeNode.source.children.length === 0;
+        let isBillPriceCalc = me.project.projSetting.billsCalcMode === billsPrice;
+
+        if (isRation) {                 // 清单单价计算模式下的叶子清单:取自己的计算程序ID,找到自己的计算程序计算。
+            me.calculate(treeNode);
+            rst = treeNode.data.calcTemplate.calcItems;
+        }
+        else if (isLeafBill) {
+            let ct = '';
+            if (treeNode.children && treeNode.children.length > 0){
+                if (treeNode.children[0].sourceType == me.project.Ration.getSourceType()){
+                    ct = childrenType.ration;
+                }
+                else if (treeNode.children[0].sourceType == me.project.VolumePrice.getSourceType()){
+                    ct = childrenType.volumePrice;
+                };
             }
             }
+            else{
+                ct = childrenType.formula;
+            };
 
 
-            this.calc.changed = false;
+            if (ct == childrenType.ration){
+                if (isBillPriceCalc){   // 清单单价计算模式下的叶子清单:取自己的计算程序ID,找到自己的计算程序计算。
+                    me.calculate(treeNode);
+                    rst = treeNode.data.calcTemplate.calcItems;
+                }else{                  // 前三种计算模式下的叶子清单:汇总定额的计算程序的费用类别
+                    rst = me.gatherFeeTypes(treeNode, CP_GatherType.rations);
+                };
+            }else if (ct == childrenType.volumePrice){
+                rst = [];
+            }else if (ct == childrenType.formula){
+                rst = [];
+            };
+        }
+        else if (isBill){    // 父清单:汇总子清单的费用类别
+            rst = me.gatherFeeTypes(treeNode, CP_GatherType.bills);
         };
         };
+
+        return rst;
     }
     }
 }
 }

+ 12 - 0
web/building_saas/main/js/models/main_consts.js

@@ -33,4 +33,16 @@ const CP_Col_Width = {          // 多处计算程序界面的列宽统一设置
     memo: 110,
     memo: 110,
     unitFee: 90,
     unitFee: 90,
     totalFee: 90
     totalFee: 90
+};
+
+const CP_GatherType = {
+    rations: 'rations',
+    bills: 'bills'
+};
+
+const childrenType = {
+    ration: 'ration',
+    bill: 'bill',
+    volumePrice: 'volumePrice',
+    formula: 'formula'
 };
 };

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

@@ -107,7 +107,7 @@ var Ration = {
             return newData;
             return newData;
         };
         };
 
 
-        ration.prototype.getBillsSortRation = function (billsID) {
+        ration.prototype.getBillsSortRation = function (billsID) {     // 该方法只适用于叶子清单
             var rations = this.datas.filter(function (data) {
             var rations = this.datas.filter(function (data) {
                 return data[project.masterField.ration] === billsID;
                 return data[project.masterField.ration] === billsID;
             });
             });
@@ -117,6 +117,40 @@ var Ration = {
             return rations;
             return rations;
         };
         };
 
 
+        // CSL, 2017-11-13 取任何清单(父清单、叶子清单)下的所有定额
+        ration.prototype.getRationsByNode = function (billNode) {
+            let rations = [];
+            let sBills = 'bills';
+            if (billNode.sourceType != sBills) return rations;
+
+            let IDs = [];
+            function getSubBillsIDs(node) {
+                if (!node) return;
+                if (node.sourceType != sBills) return;
+                if (!node.children || node.children.length == 0 || node.children[0].sourceType != sBills)
+                    IDs.push(node.data.ID)
+                else
+                    getSubBillsIDs(node.children[0]);
+                getSubBillsIDs(node.nextSibling);
+            };
+
+            if (billNode.source.children.length == 0)
+                IDs.push(billNode.data.ID)
+            else
+                getSubBillsIDs(billNode.children[0]);
+
+            for (let id of IDs){
+                let subRations = this.datas.filter(function (data) {
+                    return data[project.masterField.ration] === id;
+                });
+                rations.push(...subRations);
+            };
+            rations.sort(function (x, y) {
+                return x.serialNo - y.serialNo;
+            });
+            return rations;
+        };
+
         ration.prototype.getInsertRationData = function (billsID, preRation) {
         ration.prototype.getInsertRationData = function (billsID, preRation) {
             var br = this.getBillsSortRation(billsID);
             var br = this.getBillsSortRation(billsID);
             var updateData = [];
             var updateData = [];

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

@@ -76,7 +76,9 @@ var ration_glj = {
                         sameGlj.quantity = sameGlj.quantity + (glj.quantity * ration.quantity).toDecimal(4);
                         sameGlj.quantity = sameGlj.quantity + (glj.quantity * ration.quantity).toDecimal(4);
                     }
                     }
                 }
                 }
-            }
+            };
+
+            result = gljOprObj.combineWithProjectGlj(result);
             return result;
             return result;
         }
         }
 
 

+ 7 - 17
web/building_saas/main/js/views/calc_program_view.js

@@ -205,10 +205,10 @@ let calcProgramObj = {
             {headerName: "费用名称", headerWidth: CP_Col_Width.name, dataCode: "name", dataType: "String"},
             {headerName: "费用名称", headerWidth: CP_Col_Width.name, dataCode: "name", dataType: "String"},
             {headerName: "计算基数", headerWidth: CP_Col_Width.dispExprUser, dataCode: "dispExprUser", dataType: "String"},
             {headerName: "计算基数", headerWidth: CP_Col_Width.dispExprUser, dataCode: "dispExprUser", dataType: "String"},
             {headerName: "费率", headerWidth: CP_Col_Width.feeRate, dataCode: "feeRate", dataType: "Number"},   // precision: 3
             {headerName: "费率", headerWidth: CP_Col_Width.feeRate, dataCode: "feeRate", dataType: "Number"},   // precision: 3
-            {headerName:"费用类别", headerWidth:CP_Col_Width.displayFieldName, dataCode:"displayFieldName", dataType: "String", hAlign: "center"},
-            {headerName: "基数说明", headerWidth: CP_Col_Width.statement, dataCode: "statement", dataType: "String"},
             {headerName: "单价", headerWidth: CP_Col_Width.unitFee, dataCode: "unitFee", dataType: "Number"},  // execRst
             {headerName: "单价", headerWidth: CP_Col_Width.unitFee, dataCode: "unitFee", dataType: "Number"},  // execRst
             {headerName: "合价", headerWidth: CP_Col_Width.totalFee, dataCode: "totalFee", dataType: "Number"},
             {headerName: "合价", headerWidth: CP_Col_Width.totalFee, dataCode: "totalFee", dataType: "Number"},
+            {headerName:"费用类别", headerWidth:CP_Col_Width.displayFieldName, dataCode:"displayFieldName", dataType: "String", hAlign: "center"},
+            {headerName: "基数说明", headerWidth: CP_Col_Width.statement, dataCode: "statement", dataType: "String"},
             {headerName: "备注", headerWidth: CP_Col_Width.memo, dataCode: "memo", dataType: "String"}
             {headerName: "备注", headerWidth: CP_Col_Width.memo, dataCode: "memo", dataType: "String"}
         ],
         ],
         view: {
         view: {
@@ -228,22 +228,12 @@ let calcProgramObj = {
     showData: function (treeNode) {
     showData: function (treeNode) {
         var me = this;
         var me = this;
         me.treeNode = treeNode;
         me.treeNode = treeNode;
+        me.datas = projectObj.project.calcProgram.getCalcDatas(treeNode);
+        sheetCommonObj.initSheet(me.sheet, me.setting, me.datas.length);
+        sheetCommonObj.showData(me.sheet, me.setting, me.datas);
 
 
-        let isRation = treeNode.sourceType === projectObj.project.Ration.getSourceType();
-        let isBill = treeNode.sourceType === projectObj.project.Bills.getSourceType();
-        let isLeafBill = isBill && treeNode.source.children && treeNode.source.children.length === 0;
-        let isBillPriceCalc = projectObj.project.projSetting.billsCalcMode === billsPrice;
-
-        if (isRation || (isLeafBill && isBillPriceCalc)) {
-            projectObj.project.calcProgram.calculate(treeNode);
-            me.datas = me.treeNode.data.calcTemplate.calcItems;
-            sheetCommonObj.initSheet(me.sheet, me.setting, me.datas.length);
-            sheetCommonObj.showData(me.sheet, me.setting, me.datas);
-        }
-        else if (isBill) {
-            SheetDataHelper.loadSheetHeader(calcProgramSetting, me.sheet);
-            SheetDataHelper.loadSheetData(calcProgramSetting, me.sheet, baseCalcField);
-        }
+        // SheetDataHelper.loadSheetHeader(calcProgramSetting, me.sheet);
+        //  SheetDataHelper.loadSheetData(calcProgramSetting, me.sheet, baseCalcField);
     },
     },
 
 
     clearData: function (){
     clearData: function (){

+ 62 - 34
web/building_saas/main/js/views/project_view.js

@@ -139,7 +139,9 @@ var projectObj = {
             }
             }
             return nodes;
             return nodes;
         }
         }
-        value = value.toDecimal(projectObj.project.Decimal.common.quantity);
+        if (value) {
+            value = value.toDecimal(projectObj.project.Decimal.common.quantity);
+        }
         if (node.sourceType === projectObj.project.Bills.getSourceType()) {
         if (node.sourceType === projectObj.project.Bills.getSourceType()) {
             calcFees.setFee(node.data, fieldName, value);
             calcFees.setFee(node.data, fieldName, value);
             calc.calcNode(node, true);
             calc.calcNode(node, true);
@@ -250,15 +252,9 @@ var projectObj = {
             this.updateRationCode(node, value);
             this.updateRationCode(node, value);
         }
         }
     },
     },
-    mainSpreadEditEnded: function (sender, info) {
-        let project = projectObj.project;
-        let node = project.mainTree.items[info.row];
-        let colSetting = projectObj.mainController.setting.cols[info.col];
-        let fieldName = projectObj.mainController.setting.cols[info.col].data.field;
-        // 检查输入类型等
-        let value = projectObj.checkSpreadEditingText(info.editingText, colSetting);
-
-        if (value && value !== calcFees.getFee(node.data, fieldName)) {
+    updateCellValue: function (node, value, colSetting) {
+        let project = projectObj.project, fieldName = colSetting.data.field;
+        if (value !== calcFees.getFee(node.data, fieldName)) {
             if (fieldName === 'code') {
             if (fieldName === 'code') {
                 projectObj.updateCode(node, value);
                 projectObj.updateCode(node, value);
             } else if (fieldName === 'quantity' && project.quantity_detail.quantityEditChecking(value,node,fieldName)) {
             } else if (fieldName === 'quantity' && project.quantity_detail.quantityEditChecking(value,node,fieldName)) {
@@ -276,7 +272,7 @@ var projectObj = {
                     project.VolumePrice.updateField(node.source, fieldName, value, true);
                     project.VolumePrice.updateField(node.source, fieldName, value, true);
                 }
                 }
                 if (colSetting.data.wordWrap) {
                 if (colSetting.data.wordWrap) {
-                    info.sheet.autoFitRow(info.row);
+                    info.sheet.autoFitRow(node.serialNo());
                 }
                 }
                 projectObj.mainController.refreshTreeNode([node]);
                 projectObj.mainController.refreshTreeNode([node]);
             }
             }
@@ -286,6 +282,29 @@ var projectObj = {
             projectObj.mainController.refreshTreeNode([node], false);
             projectObj.mainController.refreshTreeNode([node], false);
         }
         }
     },
     },
+    mainSpreadEditEnded: function (sender, info) {
+        let project = projectObj.project;
+        let node = project.mainTree.items[info.row];
+        let colSetting = projectObj.mainController.setting.cols[info.col];
+        let fieldName = projectObj.mainController.setting.cols[info.col].data.field;
+        // 检查输入类型等
+        let value = projectObj.checkSpreadEditingText(info.editingText, colSetting);
+
+        projectObj.updateCellValue(node, value, colSetting);
+    },
+    mainSpreadRangeChanged: function (sender, info) {
+        let project = projectObj.project, setting = projectObj.mainController.setting;
+        if (info.changedCells.length > 0) {
+            for (let changedCell of info.changedCells) {
+                let cell = info.sheet.getCell(changedCell.row, changedCell.col);
+                let node = project.mainTree.items[changedCell.row];
+                let colSetting = setting.cols[changedCell.col];
+                let value = projectObj.checkSpreadEditingText(cell.text(), colSetting);
+
+                projectObj.updateCellValue(node, value, colSetting);
+            }
+        }
+    },
     checkMainSpread: function () {
     checkMainSpread: function () {
         if (!this.mainSpread) {
         if (!this.mainSpread) {
             this.mainSpread = SheetDataHelper.createNewSpread($('#billsSpread')[0]);
             this.mainSpread = SheetDataHelper.createNewSpread($('#billsSpread')[0]);
@@ -338,6 +357,7 @@ var projectObj = {
                 that.mainController.bind(TREE_SHEET_CONTROLLER.eventName.treeSelectedChanged, that.treeSelectedChanged);
                 that.mainController.bind(TREE_SHEET_CONTROLLER.eventName.treeSelectedChanged, that.treeSelectedChanged);
 
 
                 that.mainSpread.bind(GC.Spread.Sheets.Events.EditEnded, that.mainSpreadEditEnded);
                 that.mainSpread.bind(GC.Spread.Sheets.Events.EditEnded, that.mainSpreadEditEnded);
+                that.mainSpread.bind(GC.Spread.Sheets.Events.RangeChanged, that.mainSpreadRangeChanged);
                 that.loadMainSpreadContextMenu();
                 that.loadMainSpreadContextMenu();
             }
             }
             else {
             else {
@@ -425,7 +445,7 @@ var projectObj = {
                         return !selected;
                         return !selected;
                     },
                     },
                     callback: function () {
                     callback: function () {
-                        var selected = controller.tree.selected;
+                        var selected = controller.tree.selected, parent = selected.parent;
                         if (selected) {
                         if (selected) {
                             if (selected.sourceType === project.Bills.getSourceType()) {
                             if (selected.sourceType === project.Bills.getSourceType()) {
                                 project.Bills.deleteBills(selected.source);
                                 project.Bills.deleteBills(selected.source);
@@ -437,6 +457,7 @@ var projectObj = {
                                 project.VolumePrice.delete(selected.source);
                                 project.VolumePrice.delete(selected.source);
                                 controller.delete();
                                 controller.delete();
                             };
                             };
+                            projectObj.converseCalculateBills(parent);
                         }
                         }
                     }
                     }
                 },
                 },
@@ -452,16 +473,18 @@ var projectObj = {
     },
     },
     // 计算node及node的所有父项
     // 计算node及node的所有父项
     converseCalculateBills: function (node) {
     converseCalculateBills: function (node) {
-        let calc = new BillsCalcHelper(this.project);
-        calc.calcNode(node, true);
-        let cur = node, nodes = [];
-        while (cur) {
-            nodes.push(cur);
-            cur = cur.parent;
+        if (node) {
+            let calc = new BillsCalcHelper(this.project);
+            calc.calcNode(node, true);
+            let cur = node, nodes = [];
+            while (cur) {
+                nodes.push(cur);
+                cur = cur.parent;
+            }
+            this.mainController.refreshTreeNode(nodes, false);
+            this.project.Bills.updateNodes(nodes, true);
+            calc = null;
         }
         }
-        this.mainController.refreshTreeNode(nodes, false);
-        this.project.Bills.updateNodes(nodes, true);
-        calc = null;
     },
     },
     // 计算全部清单
     // 计算全部清单
     calculateAll: function () {
     calculateAll: function () {
@@ -487,7 +510,7 @@ $('#insert').click(function () {
 });
 });
 $('#delete').click(function () {
 $('#delete').click(function () {
     var controller = projectObj.mainController, project = projectObj.project;
     var controller = projectObj.mainController, project = projectObj.project;
-    var selected = controller.tree.selected;
+    var selected = controller.tree.selected, parent = selected.parent;
 
 
     if (selected) {
     if (selected) {
         if (selected.sourceType === project.Bills.getSourceType()) {
         if (selected.sourceType === project.Bills.getSourceType()) {
@@ -500,15 +523,17 @@ $('#delete').click(function () {
             project.VolumePrice.delete(selected.source);
             project.VolumePrice.delete(selected.source);
             controller.delete();
             controller.delete();
         };
         };
+        projectObj.converseCalculateBills(parent);
     }
     }
 });
 });
 $('#upLevel').click(function () {
 $('#upLevel').click(function () {
     var controller = projectObj.mainController, project = projectObj.project;
     var controller = projectObj.mainController, project = projectObj.project;
-    var selected = controller.tree.selected;
+    var selected = controller.tree.selected, orgParent = selected.parent;
 
 
     if (selected && selected.sourceType === project.Bills.getSourceType()) {
     if (selected && selected.sourceType === project.Bills.getSourceType()) {
         project.Bills.upLevelBills(selected.source);
         project.Bills.upLevelBills(selected.source);
         controller.upLevel();
         controller.upLevel();
+        projectObj.converseCalculateBills(orgParent);
     }
     }
 });
 });
 $('#downLevel').click(function () {
 $('#downLevel').click(function () {
@@ -516,12 +541,13 @@ $('#downLevel').click(function () {
     var selected = controller.tree.selected;
     var selected = controller.tree.selected;
     if (selected && selected.sourceType === project.Bills.getSourceType()) {
     if (selected && selected.sourceType === project.Bills.getSourceType()) {
         project.Bills.downLevelBills(selected.source);
         project.Bills.downLevelBills(selected.source);
-        controller.downLevel();
+        controller.downLevel();       
+        projectObj.converseCalculateBills(selected.parent);
     }
     }
 });
 });
 $('#upMove').click(function () {
 $('#upMove').click(function () {
     var controller = projectObj.mainController, project = projectObj.project;
     var controller = projectObj.mainController, project = projectObj.project;
-    var selected = controller.tree.selected, pre, preSerialNo;
+    var selected = controller.tree.selected, pre = selected.preSibling, preSerialNo;
 
 
     if (selected.sourceType === project.Bills.getSourceType()) {
     if (selected.sourceType === project.Bills.getSourceType()) {
         project.Bills.upMoveBills(selected.source);
         project.Bills.upMoveBills(selected.source);
@@ -538,15 +564,17 @@ $('#downMove').click(function () {
     var controller = projectObj.mainController, project = projectObj.project;
     var controller = projectObj.mainController, project = projectObj.project;
     var selected = controller.tree.selected, next, nextSerialNo;
     var selected = controller.tree.selected, next, nextSerialNo;
 
 
-    if (selected.sourceType === project.Bills.getSourceType()) {
-        project.Bills.downMoveBills(selected.source);
-        controller.downMove();
-    } else if (selected.sourceType === project.Ration.getSourceType()) {
-        project.Ration.changePos(selected.source, selected.nextSibling.source);
-        controller.downMove();
-    } else if (selected.sourceType === project.VolumePrice.getSourceType()) {
-        project.VolumePrice.changePos(selected.source, selected.nextSibling.source);
-        controller.downMove();
+    if (selected) {
+        if (selected.sourceType === project.Bills.getSourceType()) {
+            project.Bills.downMoveBills(selected.source);
+            controller.downMove();
+        } else if (selected.sourceType === project.Ration.getSourceType()) {
+            project.Ration.changePos(selected.source, selected.nextSibling.source);
+            controller.downMove();
+        } else if (selected.sourceType === project.VolumePrice.getSourceType()) {
+            project.VolumePrice.changePos(selected.source, selected.nextSibling.source);
+            controller.downMove();
+        }
     }
     }
 });
 });